diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c index e56e1edcee..9447000690 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c @@ -11,7 +11,6 @@ static int errno; #include #include #include -#include #include #include #include @@ -19,6 +18,11 @@ static int errno; #include #include +#define SHUTDOWN_INVALID -1 +#define SHUTDOWN_POWEROFF 0 +#define SHUTDOWN_REBOOT 1 +#define SHUTDOWN_SUSPEND 2 + void machine_restart(char * __unused) { /* We really want to get pending console data out before we die. */ @@ -53,7 +57,7 @@ EXPORT_SYMBOL(machine_power_off); */ /* Ignore multiple shutdown requests. */ -static int shutting_down = -1; +static int shutting_down = SHUTDOWN_INVALID; static void __do_suspend(void) { @@ -126,8 +130,6 @@ static void __do_suspend(void) xenbus_suspend(); - ctrl_if_suspend(); - irq_suspend(); gnttab_suspend(); @@ -140,7 +142,7 @@ static void __do_suspend(void) HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT); - shutting_down = -1; + shutting_down = SHUTDOWN_INVALID; memcpy(&xen_start_info, &suspend_record->resume_info, sizeof(xen_start_info)); @@ -163,8 +165,6 @@ static void __do_suspend(void) irq_resume(); - ctrl_if_resume(); - xenbus_resume(); #ifdef CONFIG_SMP @@ -204,7 +204,7 @@ static int shutdown_process(void *__unused) switch ( shutting_down ) { - case CMSG_SHUTDOWN_POWEROFF: + case SHUTDOWN_POWEROFF: if ( execve("/sbin/poweroff", poweroff_argv, envp) < 0 ) { sys_reboot(LINUX_REBOOT_MAGIC1, @@ -214,7 +214,7 @@ static int shutdown_process(void *__unused) } break; - case CMSG_SHUTDOWN_REBOOT: + case SHUTDOWN_REBOOT: if ( execve("/sbin/reboot", restart_argv, envp) < 0 ) { sys_reboot(LINUX_REBOOT_MAGIC1, @@ -225,7 +225,7 @@ static int shutdown_process(void *__unused) break; } - shutting_down = -1; /* could try again */ + shutting_down = SHUTDOWN_INVALID; /* could try again */ return 0; } @@ -234,7 +234,7 @@ static void __shutdown_handler(void *unused) { int err; - if ( shutting_down != CMSG_SHUTDOWN_SUSPEND ) + if ( shutting_down != SHUTDOWN_SUSPEND ) { err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES); if ( err < 0 ) @@ -246,42 +246,103 @@ static void __shutdown_handler(void *unused) } } -static void shutdown_handler(ctrl_msg_t *msg, unsigned long id) +static void shutdown_handler(struct xenbus_watch *watch, const char *node) { static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL); - if ( msg->subtype == CMSG_SHUTDOWN_SYSRQ ) - { - int sysrq = ((shutdown_sysrq_t *)&msg->msg[0])->key; - -#ifdef CONFIG_MAGIC_SYSRQ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - handle_sysrq(sysrq, NULL, NULL); -#else - handle_sysrq(sysrq, NULL, NULL, NULL); -#endif -#endif - } - else if ( (shutting_down == -1) && - ((msg->subtype == CMSG_SHUTDOWN_POWEROFF) || - (msg->subtype == CMSG_SHUTDOWN_REBOOT) || - (msg->subtype == CMSG_SHUTDOWN_SUSPEND)) ) - { - shutting_down = msg->subtype; + int type = -1; + + if (!xenbus_scanf("control", "shutdown", "%i", &type)) { + printk("Unable to read code in control/shutdown\n"); + return; + }; + + xenbus_printf("control", "shutdown", "%i", SHUTDOWN_INVALID); + + if ((type == SHUTDOWN_POWEROFF) || + (type == SHUTDOWN_REBOOT) || + (type == SHUTDOWN_SUSPEND)) { + shutting_down = type; schedule_work(&shutdown_work); } - else - { - printk("Ignore spurious shutdown request\n"); + +} + +#ifdef CONFIG_MAGIC_SYSRQ +static void sysrq_handler(struct xenbus_watch *watch, const char *node) +{ + char sysrq_key = '\0'; + + if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) { + printk("Unable to read sysrq code in control/sysrq\n"); + return; } - ctrl_if_send_response(msg); + xenbus_printf("control", "sysrq", "%c", '\0'); + + if (sysrq_key != '\0') { + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + handle_sysrq(sysrq_key, NULL, NULL); +#else + handle_sysrq(sysrq_key, NULL, NULL, NULL); +#endif + } +} +#endif + +static struct xenbus_watch shutdown_watch = { + .node = "control/shutdown", + .callback = shutdown_handler +}; + +#ifdef CONFIG_MAGIC_SYSRQ +static struct xenbus_watch sysrq_watch = { + .node ="control/sysrq", + .callback = sysrq_handler +}; +#endif + +static struct notifier_block xenstore_notifier; + +static int setup_shutdown_watcher(struct notifier_block *notifier, + unsigned long event, + void *data) +{ + int err1=0, err2=0; + + down(&xenbus_lock); + err1 = register_xenbus_watch(&shutdown_watch); +#ifdef CONFIG_MAGIC_SYSRQ + err2 = register_xenbus_watch(&sysrq_watch); +#endif + up(&xenbus_lock); + + if (err1) { + printk("Failed to set shutdown watcher\n"); + } + +#ifdef CONFIG_MAGIC_SYSRQ + if (err2) { + printk("Failed to set sysrq watcher\n"); + } +#endif + + return NOTIFY_STOP; } static int __init setup_shutdown_event(void) { - ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0); + + xenstore_notifier.notifier_call = setup_shutdown_watcher; + + if (xen_start_info.store_evtchn) { + setup_shutdown_watcher(&xenstore_notifier, 0, NULL); + } else { + register_xenstore_notifier(&xenstore_notifier); + } + return 0; } -__initcall(setup_shutdown_event); +subsys_initcall(setup_shutdown_event); diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index d440618f2d..706d351121 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -36,10 +36,16 @@ #include #include #include +#include #include "xenbus_comms.h" #define streq(a, b) (strcmp((a), (b)) == 0) +/* Protects notifier chain */ +DECLARE_MUTEX(xenstore_control); + +static struct notifier_block *xenstore_chain; + /* If something in array of ids matches this device, return it. */ static const struct xenbus_device_id * match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev) @@ -309,6 +315,26 @@ void xenbus_resume(void) up(&xenbus_lock); } +int register_xenstore_notifier(struct notifier_block *nb) +{ + int ret; + + if ((ret = down_interruptible(&xenstore_control)) != 0) + return ret; + ret = notifier_chain_register(&xenstore_chain, nb); + up(&xenstore_control); + return ret; +} +EXPORT_SYMBOL(register_xenstore_notifier); + +void unregister_xenstore_notifier(struct notifier_block *nb) +{ + down(&xenstore_control); + notifier_chain_unregister(&xenstore_chain, nb); + up(&xenstore_control); +} +EXPORT_SYMBOL(unregister_xenstore_notifier); + /* called from a thread in privcmd/privcmd.c */ int do_xenbus_probe(void *unused) { @@ -323,6 +349,15 @@ int do_xenbus_probe(void *unused) return err; } + err = notifier_call_chain(&xenstore_chain, 0, 0); + if (err == NOTIFY_BAD) { + printk("%s: calling xenstore notify chain failed\n", + __FUNCTION__); + return -EINVAL; + } + + err = 0; + /* Initialize non-xenbus drivers */ balloon_init_watcher(); diff --git a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h index af205d8945..0f30dc8ebe 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h @@ -29,6 +29,7 @@ * IN THE SOFTWARE. */ #include +#include #include /* A xenbus device. */ @@ -112,6 +113,10 @@ struct xenbus_watch void (*callback)(struct xenbus_watch *, const char *node); }; +/* notifer routines for when the xenstore comes up */ +int register_xenstore_notifier(struct notifier_block *nb); +void unregister_xenstore_notifier(struct notifier_block *nb); + int register_xenbus_watch(struct xenbus_watch *watch); void unregister_xenbus_watch(struct xenbus_watch *watch); diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py index 868836c30f..570c59d231 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -208,11 +208,15 @@ class Xend: return self.xendPost(self.domainurl(id), {'op' : 'pause' }) - def xend_domain_shutdown(self, id, reason, key=0): + def xend_domain_shutdown(self, id, reason): return self.xendPost(self.domainurl(id), {'op' : 'shutdown', - 'reason' : reason, - 'key' : key }) + 'reason' : reason}) + + def xend_domain_sysrq(self, id, key): + return self.xendPost(self.domainurl(id), + {'op' : 'sysrq', + 'key' : key}) def xend_domain_destroy(self, id, reason): return self.xendPost(self.domainurl(id), diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 157d2216cf..6527f3fb5f 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -386,7 +386,7 @@ class XendDomain: except Exception, ex: raise XendError(str(ex)) - def domain_shutdown(self, id, reason='poweroff', key=0): + def domain_shutdown(self, id, reason='poweroff'): """Shutdown domain (nicely). - poweroff: restart according to exit code and restart mode - reboot: restart on exit @@ -402,11 +402,18 @@ class XendDomain: eserver.inject('xend.domain.shutdown', [dominfo.name, dominfo.id, reason]) if reason == 'halt': reason = 'poweroff' - val = dominfo.shutdown(reason, key=key) - if not reason in ['suspend', 'sysrq']: + val = dominfo.shutdown(reason) + if not reason in ['suspend']: self.domain_shutdowns() return val + def domain_sysrq(self, id, key): + """Send a SysRq to a domain + """ + dominfo = self.domain_lookup(id) + val = dominfo.send_sysrq(key) + return val + def domain_shutdowns(self): """Process pending domain shutdowns. Destroys domains whose shutdowns have timed out. diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 3e016b681f..3510f79441 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -52,13 +52,12 @@ shutdown_reasons = { DOMAIN_CRASH : "crash", } -"""Map shutdown reasons to the message type to use. +"""Map shutdown reasons to codes """ -shutdown_messages = { - 'poweroff' : 'shutdown_poweroff_t', - 'reboot' : 'shutdown_reboot_t', - 'suspend' : 'shutdown_suspend_t', - 'sysrq' : 'shutdown_sysrq_t', +shutdown_codes = { + 'poweroff' : DOMAIN_POWEROFF, + 'reboot' : DOMAIN_REBOOT, + 'suspend' : DOMAIN_SUSPEND, } RESTART_ALWAYS = 'always' @@ -152,8 +151,6 @@ class XendDomainInfo: vm = cls(db) vm.construct(config) vm.saveToDB(sync=True) - # Flush info to xenstore immediately - vm.exportToDB() return vm @@ -941,19 +938,20 @@ class XendDomainInfo: self.channel.writeRequest(msg) - def shutdown(self, reason, key=0): - msgtype = shutdown_messages.get(reason) - if not msgtype: + def shutdown(self, reason): + reasonid = shutdown_codes.get(reason) + if reasonid == None: raise XendError('invalid reason:' + reason) - extra = {} - if reason == 'sysrq': - extra['key'] = key - if self.channel: - msg = messages.packMsg(msgtype, extra) - self.channel.writeRequest(msg) - if not reason in ['suspend', 'sysrq']: - self.shutdown_pending = {'start':time.time(), 'reason':reason, - 'key':key} + db = self.db.addChild("/control"); + db['shutdown'] = '%i' % reasonid; + db.saveDB(save=True); + if not reason in ['suspend']: + self.shutdown_pending = {'start':time.time(), 'reason':reason} + + def send_sysrq(self, key=0): + db = self.db.addChild("/control"); + db['sysrq'] = '%c' % key; + db.saveDB(save=True); def shutdown_time_left(self, timeout): if not self.shutdown_pending: diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py index 6e51e69518..d0249dab7b 100644 --- a/tools/python/xen/xend/server/SrvDomain.py +++ b/tools/python/xen/xend/server/SrvDomain.py @@ -39,13 +39,21 @@ class SrvDomain(SrvDir): def op_shutdown(self, op, req): fn = FormFn(self.xd.domain_shutdown, [['dom', 'int'], - ['reason', 'str'], - ['key', 'int']]) + ['reason', 'str']]) val = fn(req.args, {'dom': self.dom.id}) req.setResponseCode(http.ACCEPTED) req.setHeader("Location", "%s/.." % req.prePathURL()) return val + def op_sysrq(self, op, req): + fn = FormFn(self.xd.domain_sysrq, + [['dom', 'int'], + ['key', 'int']]) + val = fn(req.args, {'dom' : self.dom.id}) + req.setResponseCode(http.ACCEPTED) + req.setHeader("Location", "%s/.." % req.prePathURL()) + return val + def op_destroy(self, op, req): fn = FormFn(self.xd.domain_destroy, [['dom', 'int'], diff --git a/tools/python/xen/xm/sysrq.py b/tools/python/xen/xm/sysrq.py index 44827af094..12b2da22fe 100644 --- a/tools/python/xen/xm/sysrq.py +++ b/tools/python/xen/xm/sysrq.py @@ -21,9 +21,6 @@ gopts.opt('help', short='h', fn=set_true, default=0, use="Print this help.") -def sysrq(dom, req): - server.xend_domain_shutdown(dom, 'sysrq', req) - def main(argv): opts = gopts args = opts.parse(argv) @@ -36,4 +33,4 @@ def main(argv): if len(args) < 2: opts.err('Missing sysrq character') dom = args[0] req = ord(args[1][0]) - sysrq(dom, req) + server.xend_domain_sysrq(dom, req)