[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] Early ACPI events prevent subsequent ACPI functionality on xen 4.3 + HVM domU
> > @@ -185,7 +185,7 @@ struct shutdown_handler { > > > static void do_poweroff(void) > > > { > > > shutting_down = SHUTDOWN_POWEROFF; > > > - orderly_poweroff(false); > > > + orderly_poweroff(system_state != SYSTEM_RUNNING ? true : false); > > > > Does this DTRT for systems in SYSTEM_{HALTED,POWEROFF}? I suppose under > > those circumstances forcing is the desired action, insn't it > > Yes. And there is also a guard (shutting_down) that gets set on > drivers/xen/manage.c so that the 'do_poweroff' will only get called > once. Which would guard against us powering off and then > receiving another 'xl shutdown' when the the system_state is in > HALTED or POWEROFF. > > But I hadn't tested the case where the user does 'poweroff' > and at the same time the system admin does 'xl shutdown'. > > Depending on the race, the state will be SYSTEM_RUNNING or > SYSTEM_POWER_OFF. If SYSTEM_RUNNING we just end up making > a duplicate call to 'poweroff' (while it is running). > > That will fail or execute (And if executed then it will be > stuck in the reboot_mutex mutex). But nobody will care b/c the > machine is in poweroff sequence. Right. > If the state is SYSTEM_POWER_OFF then we end up making > a duplicate call to kernel_power_off. There is no locking > there so we walk in the same steps as what 'poweroff' > has been doing. > > This code in kernel/reboot.c doesn't look that safe when it > comes to a user-invoked 'poweroff' operation and a kernel > 'orderly_poweroff' operation. Yes. > Perhaps what we should do is just: > > if (system_state == SYSTEM_BOOTING) > orderly_poweroff(true); > else if (system_state == SYSTEM_RUNNING) > orderly_poweroff(false); > else > printk("Shutdown in progress. Ignoring xl shutdown"); (nb: switch() ;-)). I would also avoiding saying xl since it may not be true. "Ignoring Xen toolstack shutdown" or something > But then 'system_state' is not guarded by a spinlock or such. Thought > it is guarded by the xenwatch mutex. system_state is a core global though, so it must surely also be touched outside of xen code and therefore outside of xenwatch mutex. maybe you meant s/system_state/shutting_down/? > Perhaps to be extra safe we should add ourselves to the > register_reboot_notifier like so (not compile tested) I think this only makes sense if you did mean s/system_state/shutting_down/ above, so I'll assume that to be the case. It's a shame this has to expose the watch mutex outside of the core xs code. Perhaps the core code could add the notifier itself and in turn call a manage.c notification function with the lock already held? > > diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c > index fe1c0a6..fb43db6 100644 > --- a/drivers/xen/manage.c > +++ b/drivers/xen/manage.c > @@ -36,7 +36,8 @@ enum shutdown_state { > SHUTDOWN_HALT = 4, > }; > > -/* Ignore multiple shutdown requests. */ > +/* Ignore multiple shutdown requests. Our mutex for this is that > + * shutdown handler is called with a mutex from xenwatch. */ > static enum shutdown_state shutting_down = SHUTDOWN_INVALID; > > struct suspend_info { > @@ -185,7 +186,12 @@ struct shutdown_handler { > static void do_poweroff(void) > { > shutting_down = SHUTDOWN_POWEROFF; > - orderly_poweroff(system_state != SYSTEM_RUNNING ? true : false); > + if (system_state == SYSTEM_RUNNING) > + orderly_poweroff(false); > + else if (system_state == SYSTEM_BOOTING) > + orderly_poweroff(true); > + else > + printk(KERN_WARNING "Ignorning shutdown request as poweroff in > progress.\n"); > } > > static void do_reboot(void) > @@ -250,7 +256,29 @@ static void shutdown_handler(struct xenbus_watch *watch, > > kfree(str); > } > +/* > + * This function is called when the system is being rebooted. > + */ > +static int > +xxen_system_reboot(struct notifier_block *nb, unsigned long event, void > *unused) > +{ > + switch (event) { > + case SYS_RESTART: > + case SYS_HALT: > + case SYS_POWER_OFF: > + default: > + mutex_lock(&xenwatch_mutex); > + shutting_down = SHUTDOWN_POWEROFF; > + mutex_unlock(&xenwatch_mutex); > + break; > + } > + > + return NOTIFY_DONE; > +} > > +static struct notifier_block xen_shutdown_notifier = { > + .notifier_call = xen_system_reboot, > +}; > #ifdef CONFIG_MAGIC_SYSRQ > static void sysrq_handler(struct xenbus_watch *watch, const char **vec, > unsigned int len) > @@ -308,7 +336,11 @@ static int setup_shutdown_watcher(void) > return err; > } > #endif > - > + err = register_reboot_notifier(&xen_shutdown_notifier); > + if (err) { > + pr_warn("Failed to register shutdown notifier\n"); > + return err; > + } > return 0; > } > > diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c > index b6d5fff..ac25752 100644 > --- a/drivers/xen/xenbus/xenbus_xs.c > +++ b/drivers/xen/xenbus/xenbus_xs.c > @@ -122,7 +122,7 @@ static DEFINE_SPINLOCK(watch_events_lock); > * carrying out work. > */ > static pid_t xenwatch_pid; > -static DEFINE_MUTEX(xenwatch_mutex); > +DEFINE_MUTEX(xenwatch_mutex); > static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq); > > static int get_error(const char *errorstring) > diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h > index 40abaf6..57b3370 100644 > --- a/include/xen/xenbus.h > +++ b/include/xen/xenbus.h > @@ -125,7 +125,7 @@ struct xenbus_transaction > { > u32 id; > }; > - > +extern struct mutex xenwatch_mutex; > /* Nil transaction ID. */ > #define XBT_NIL ((struct xenbus_transaction) { 0 }) > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |