[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] Convert shutdown to use xenstore



The attached patch:

1. Converts the shutdown driver and xend to use the store instead of
   control messages, 

2. Includes Anthony's xenstore notification code, and

3. Changes xend so that sysrq's are no longer sent as "special case"
   shutdown messages.  Store keys are cheap, so making the sysrq
   delivery less obscure is good.

I think I have made all of the appropriate modifications to Xend, but
it is complex, so I may have missed something.  Comments are welcome.

Signed-off-by: Dan Smith <danms@xxxxxxxxxx>
Signed-off-by: Anthony Liguori <aliguori@xxxxxxxxxx>

diff -r 60c4cd9ebaa1 linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c     Wed Aug  3 16:11:32 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c     Wed Aug  3 15:43:36 2005
@@ -11,7 +11,6 @@
 #include <linux/sysrq.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
-#include <asm-xen/ctrl_if.h>
 #include <asm-xen/evtchn.h>
 #include <asm-xen/hypervisor.h>
 #include <asm-xen/xen-public/dom0_ops.h>
@@ -19,6 +18,11 @@
 #include <asm-xen/queues.h>
 #include <asm-xen/xenbus.h>
 
+#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 @@
  */
 
 /* Ignore multiple shutdown requests. */
-static int shutting_down = -1;
+static int shutting_down = SHUTDOWN_INVALID;
 
 static void __do_suspend(void)
 {
@@ -126,8 +130,6 @@
 
     xenbus_suspend();
 
-    ctrl_if_suspend();
-
     irq_suspend();
 
     gnttab_suspend();
@@ -140,7 +142,7 @@
 
     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 @@
 
     irq_resume();
 
-    ctrl_if_resume();
-
     xenbus_resume();
 
 #ifdef CONFIG_SMP
@@ -204,7 +204,7 @@
 
     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 @@
         }
         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 @@
         break;
     }
 
-    shutting_down = -1; /* could try again */
+    shutting_down = SHUTDOWN_INVALID; /* could try again */
 
     return 0;
 }
@@ -234,7 +234,7 @@
 {
     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(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;
-       
+    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);
+    }
+
+}
+
 #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;
+    }
+
+    xenbus_printf("control", "sysrq", "%c", '\0');
+
+    if (sysrq_key != '\0') {
+
 #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;
-        schedule_work(&shutdown_work);
-    }
-    else
-    {
-        printk("Ignore spurious shutdown request\n");
-    }
-
-    ctrl_if_send_response(msg);
+        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 -r 60c4cd9ebaa1 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Wed Aug  3 
16:11:32 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c    Wed Aug  3 
15:43:36 2005
@@ -36,9 +36,15 @@
 #include <linux/ctype.h>
 #include <linux/fcntl.h>
 #include <stdarg.h>
+#include <linux/notifier.h>
 #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 *
@@ -309,6 +315,26 @@
        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 @@
                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 -r 60c4cd9ebaa1 linux-2.6-xen-sparse/include/asm-xen/xenbus.h
--- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h     Wed Aug  3 16:11:32 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h     Wed Aug  3 15:43:36 2005
@@ -29,6 +29,7 @@
  * IN THE SOFTWARE.
  */
 #include <linux/device.h>
+#include <linux/notifier.h>
 #include <asm/semaphore.h>
 
 /* A xenbus device. */
@@ -112,6 +113,10 @@
        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 -r 60c4cd9ebaa1 tools/python/xen/xend/XendClient.py
--- a/tools/python/xen/xend/XendClient.py       Wed Aug  3 16:11:32 2005
+++ b/tools/python/xen/xend/XendClient.py       Wed Aug  3 15:43:36 2005
@@ -213,11 +213,15 @@
         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 -r 60c4cd9ebaa1 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Wed Aug  3 16:11:32 2005
+++ b/tools/python/xen/xend/XendDomain.py       Wed Aug  3 15:43:36 2005
@@ -386,7 +386,7 @@
         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,9 +402,16 @@
         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):
diff -r 60c4cd9ebaa1 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Wed Aug  3 16:11:32 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py   Wed Aug  3 15:43:36 2005
@@ -52,13 +52,12 @@
     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 @@
         vm = cls(db)
         vm.construct(config)
         vm.saveToDB(sync=True)
-        # Flush info to xenstore immediately
-        vm.exportToDB()
 
         return vm
 
@@ -976,19 +973,20 @@
 
             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 -r 60c4cd9ebaa1 tools/python/xen/xend/server/SrvDomain.py
--- a/tools/python/xen/xend/server/SrvDomain.py Wed Aug  3 16:11:32 2005
+++ b/tools/python/xen/xend/server/SrvDomain.py Wed Aug  3 15:43:36 2005
@@ -41,9 +41,17 @@
     def op_shutdown(self, op, req):
         fn = FormFn(self.xd.domain_shutdown,
                     [['dom',    'int'],
-                     ['reason', 'str'],
+                     ['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})
+        val = fn(req.args, {'dom' : self.dom.id})
         req.setResponseCode(http.ACCEPTED)
         req.setHeader("Location", "%s/.." % req.prePathURL())
         return val
diff -r 60c4cd9ebaa1 tools/python/xen/xm/sysrq.py
--- a/tools/python/xen/xm/sysrq.py      Wed Aug  3 16:11:32 2005
+++ b/tools/python/xen/xm/sysrq.py      Wed Aug  3 15:43:36 2005
@@ -21,9 +21,6 @@
          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 @@
     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)
-- 
Dan Smith
IBM Linux Technology Center
Open Hypervisor Team
email: danms@xxxxxxxxxx
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.