Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xen/manage: Poweroff forcefully if user-space is not yet up.

The user can launch the guest in this sequence:

xl create -p /vm.cfg [launch, but pause it]
xl shutdown latest [sets control/shutdown=poweroff]
xl unpause latest
xl console latest [and see that the guest has completely
ignored the shutdown request]

In reality the guest hasn't ignored it. It registers a watch
and gets a notification that there is value. It then calls
the shutdown_handler which ends up calling orderly_shutdown.

Unfortunately that is so early in the bootup that there
are no user-space. Which means that the orderly_shutdown fails.
But since the force flag was set to false it continues on without
reporting.

What we really want to is to use the force when we are in the
SYSTEM_BOOTING state and not use the 'force' when SYSTEM_RUNNING.

However, if we are in the running state - and the shutdown command
has been given before the user-space has been setup, there is nothing
we can do. Worst yet, we stop ignoring the 'xl shutdown' requests!

As such, the other part of this patch is to only stop ignoring
the 'xl shutdown' when we are truly in the power off sequence.

That means the user can do multiple 'xl shutdown' and we will try
to act on them instead of ignoring them.

Fixes-Bug: http://bugs.xenproject.org/xen/bug/6
Reported-by: Alex Bligh <alex@alex.org.uk>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>

authored by

Konrad Rzeszutek Wilk and committed by
David Vrabel
eb47f712 027bd7e8

+30 -2
+30 -2
drivers/xen/manage.c
··· 198 198 void (*cb)(void); 199 199 }; 200 200 201 + static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused) 202 + { 203 + switch (code) { 204 + case SYS_DOWN: 205 + case SYS_HALT: 206 + case SYS_POWER_OFF: 207 + shutting_down = SHUTDOWN_POWEROFF; 208 + default: 209 + break; 210 + } 211 + return NOTIFY_DONE; 212 + } 201 213 static void do_poweroff(void) 202 214 { 203 - shutting_down = SHUTDOWN_POWEROFF; 204 - orderly_poweroff(false); 215 + switch (system_state) { 216 + case SYSTEM_BOOTING: 217 + orderly_poweroff(true); 218 + break; 219 + case SYSTEM_RUNNING: 220 + orderly_poweroff(false); 221 + break; 222 + default: 223 + /* Don't do it when we are halting/rebooting. */ 224 + pr_info("Ignoring Xen toolstack shutdown.\n"); 225 + break; 226 + } 205 227 } 206 228 207 229 static void do_reboot(void) ··· 329 307 .callback = shutdown_handler 330 308 }; 331 309 310 + static struct notifier_block xen_reboot_nb = { 311 + .notifier_call = poweroff_nb, 312 + }; 313 + 332 314 static int setup_shutdown_watcher(void) 333 315 { 334 316 int err; ··· 342 316 pr_err("Failed to set shutdown watcher\n"); 343 317 return err; 344 318 } 319 + 345 320 346 321 #ifdef CONFIG_MAGIC_SYSRQ 347 322 err = register_xenbus_watch(&sysrq_watch); ··· 372 345 if (!xen_domain()) 373 346 return -ENODEV; 374 347 register_xenstore_notifier(&xenstore_notifier); 348 + register_reboot_notifier(&xen_reboot_nb); 375 349 376 350 return 0; 377 351 }