Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / arch / x86 / xen / manage.c
blobaa7af9e6abc05ac622da6930ab87e8f731f802bd
1 /*
2 * Handle extern requests for shutdown, reboot and sysrq
3 */
4 #include <linux/kernel.h>
5 #include <linux/err.h>
6 #include <linux/reboot.h>
7 #include <linux/sysrq.h>
9 #include <xen/xenbus.h>
11 #define SHUTDOWN_INVALID -1
12 #define SHUTDOWN_POWEROFF 0
13 #define SHUTDOWN_SUSPEND 2
14 /* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
15 * report a crash, not be instructed to crash!
16 * HALT is the same as POWEROFF, as far as we're concerned. The tools use
17 * the distinction when we return the reason code to them.
19 #define SHUTDOWN_HALT 4
21 /* Ignore multiple shutdown requests. */
22 static int shutting_down = SHUTDOWN_INVALID;
24 static void shutdown_handler(struct xenbus_watch *watch,
25 const char **vec, unsigned int len)
27 char *str;
28 struct xenbus_transaction xbt;
29 int err;
31 if (shutting_down != SHUTDOWN_INVALID)
32 return;
34 again:
35 err = xenbus_transaction_start(&xbt);
36 if (err)
37 return;
39 str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
40 /* Ignore read errors and empty reads. */
41 if (XENBUS_IS_ERR_READ(str)) {
42 xenbus_transaction_end(xbt, 1);
43 return;
46 xenbus_write(xbt, "control", "shutdown", "");
48 err = xenbus_transaction_end(xbt, 0);
49 if (err == -EAGAIN) {
50 kfree(str);
51 goto again;
54 if (strcmp(str, "poweroff") == 0 ||
55 strcmp(str, "halt") == 0)
56 orderly_poweroff(false);
57 else if (strcmp(str, "reboot") == 0)
58 ctrl_alt_del();
59 else {
60 printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
61 shutting_down = SHUTDOWN_INVALID;
64 kfree(str);
67 static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
68 unsigned int len)
70 char sysrq_key = '\0';
71 struct xenbus_transaction xbt;
72 int err;
74 again:
75 err = xenbus_transaction_start(&xbt);
76 if (err)
77 return;
78 if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
79 printk(KERN_ERR "Unable to read sysrq code in "
80 "control/sysrq\n");
81 xenbus_transaction_end(xbt, 1);
82 return;
85 if (sysrq_key != '\0')
86 xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
88 err = xenbus_transaction_end(xbt, 0);
89 if (err == -EAGAIN)
90 goto again;
92 if (sysrq_key != '\0')
93 handle_sysrq(sysrq_key, NULL);
96 static struct xenbus_watch shutdown_watch = {
97 .node = "control/shutdown",
98 .callback = shutdown_handler
101 static struct xenbus_watch sysrq_watch = {
102 .node = "control/sysrq",
103 .callback = sysrq_handler
106 static int setup_shutdown_watcher(void)
108 int err;
110 err = register_xenbus_watch(&shutdown_watch);
111 if (err) {
112 printk(KERN_ERR "Failed to set shutdown watcher\n");
113 return err;
116 err = register_xenbus_watch(&sysrq_watch);
117 if (err) {
118 printk(KERN_ERR "Failed to set sysrq watcher\n");
119 return err;
122 return 0;
125 static int shutdown_event(struct notifier_block *notifier,
126 unsigned long event,
127 void *data)
129 setup_shutdown_watcher();
130 return NOTIFY_DONE;
133 static int __init setup_shutdown_event(void)
135 static struct notifier_block xenstore_notifier = {
136 .notifier_call = shutdown_event
138 register_xenstore_notifier(&xenstore_notifier);
140 return 0;
143 subsys_initcall(setup_shutdown_event);