2 * Handle extern requests for shutdown, reboot and sysrq
4 #include <linux/kernel.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
)
28 struct xenbus_transaction xbt
;
31 if (shutting_down
!= SHUTDOWN_INVALID
)
35 err
= xenbus_transaction_start(&xbt
);
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);
46 xenbus_write(xbt
, "control", "shutdown", "");
48 err
= xenbus_transaction_end(xbt
, 0);
54 if (strcmp(str
, "poweroff") == 0 ||
55 strcmp(str
, "halt") == 0)
56 orderly_poweroff(false);
57 else if (strcmp(str
, "reboot") == 0)
60 printk(KERN_INFO
"Ignoring shutdown request: %s\n", str
);
61 shutting_down
= SHUTDOWN_INVALID
;
67 static void sysrq_handler(struct xenbus_watch
*watch
, const char **vec
,
70 char sysrq_key
= '\0';
71 struct xenbus_transaction xbt
;
75 err
= xenbus_transaction_start(&xbt
);
78 if (!xenbus_scanf(xbt
, "control", "sysrq", "%c", &sysrq_key
)) {
79 printk(KERN_ERR
"Unable to read sysrq code in "
81 xenbus_transaction_end(xbt
, 1);
85 if (sysrq_key
!= '\0')
86 xenbus_printf(xbt
, "control", "sysrq", "%c", '\0');
88 err
= xenbus_transaction_end(xbt
, 0);
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)
110 err
= register_xenbus_watch(&shutdown_watch
);
112 printk(KERN_ERR
"Failed to set shutdown watcher\n");
116 err
= register_xenbus_watch(&sysrq_watch
);
118 printk(KERN_ERR
"Failed to set sysrq watcher\n");
125 static int shutdown_event(struct notifier_block
*notifier
,
129 setup_shutdown_watcher();
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
);
143 subsys_initcall(setup_shutdown_event
);