summaryrefslogtreecommitdiff
path: root/drivers/xen/manage.c
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2011-02-17 11:04:20 +0000
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2011-02-25 16:43:09 +0000
commit552717231e50b478dfd19d63fd97879476ae051d (patch)
tree6ed6a314b8b4e2ee266e33fdf450c48704df5cbc /drivers/xen/manage.c
parente057a4b6e0eb6701f6ec923be2075d4984cef51a (diff)
xen: do not respond to unknown xenstore control requests
The PV xenbus control/shutdown node is written by the toolstack as a request to the guest to perform a particular action (shutdown, reboot, suspend etc). The guest is expected to acknowledge that it will complete a request by clearing the control node. Previously it would acknowledge any request, even if it did not know what to do with it. Specifically in the case where CONFIG_PM_SLEEP is not enabled the kernel would acknowledge a suspend request even though it was not actually going to do anything. Instead make the kernel only acknowledge requests if it is actually going to do something with it. This will improve the toolstack's ability to diagnose and deal with failures. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/manage.c')
-rw-r--r--drivers/xen/manage.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index b2a8d7856ce3..972bf783a182 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -172,12 +172,39 @@ out:
}
#endif /* CONFIG_PM_SLEEP */
+struct shutdown_handler {
+ const char *command;
+ void (*cb)(void);
+};
+
+static void do_poweroff(void)
+{
+ shutting_down = SHUTDOWN_POWEROFF;
+ orderly_poweroff(false);
+}
+
+static void do_reboot(void)
+{
+ shutting_down = SHUTDOWN_POWEROFF; /* ? */
+ ctrl_alt_del();
+}
+
static void shutdown_handler(struct xenbus_watch *watch,
const char **vec, unsigned int len)
{
char *str;
struct xenbus_transaction xbt;
int err;
+ static struct shutdown_handler handlers[] = {
+ { "poweroff", do_poweroff },
+ { "halt", do_poweroff },
+ { "reboot", do_reboot },
+#ifdef CONFIG_PM_SLEEP
+ { "suspend", do_suspend },
+#endif
+ {NULL, NULL},
+ };
+ static struct shutdown_handler *handler;
if (shutting_down != SHUTDOWN_INVALID)
return;
@@ -194,7 +221,14 @@ static void shutdown_handler(struct xenbus_watch *watch,
return;
}
- xenbus_write(xbt, "control", "shutdown", "");
+ for (handler = &handlers[0]; handler->command; handler++) {
+ if (strcmp(str, handler->command) == 0)
+ break;
+ }
+
+ /* Only acknowledge commands which we are prepared to handle. */
+ if (handler->cb)
+ xenbus_write(xbt, "control", "shutdown", "");
err = xenbus_transaction_end(xbt, 0);
if (err == -EAGAIN) {
@@ -202,17 +236,8 @@ static void shutdown_handler(struct xenbus_watch *watch,
goto again;
}
- if (strcmp(str, "poweroff") == 0 ||
- strcmp(str, "halt") == 0) {
- shutting_down = SHUTDOWN_POWEROFF;
- orderly_poweroff(false);
- } else if (strcmp(str, "reboot") == 0) {
- shutting_down = SHUTDOWN_POWEROFF; /* ? */
- ctrl_alt_del();
-#ifdef CONFIG_PM_SLEEP
- } else if (strcmp(str, "suspend") == 0) {
- do_suspend();
-#endif
+ if (handler->cb) {
+ handler->cb();
} else {
printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
shutting_down = SHUTDOWN_INVALID;