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

[Xen-devel] PATCH: ability to send sysrqs to Linux domains



Here's the promised patch against a recent 2.01 snapshot to allow you to send sysrqs to running Linux kernels. I went with Keir's suggestion of adding a sub-reason code to the shutdown message with a 1-byte payload specifying which key was pressed. Hope it's acceptable for the main tree; I will happily alter it to spec if any of the maintainers have suggestions for better structuring it.

It adds the CONFIG_MAGIC_SYSRQ option to the Linux kernel which you need to turn on for a guest to work with it, then you can just do e.g. "xm sysrq domainname s" to sync your discs.

cheers,

--
Matthew Bloch                             Bytemark Hosting
                                http://www.bytemark.co.uk/
                phone UK: 0845 004 3 004 US: 1-877 BYTEMAR
          Dedicated Linux hosts from 15ukp ($26) per month

diff -urN xen-2.0/linux-2.6.9-xen-sparse/arch/xen/Kconfig 
xen-2.0-sysrq/linux-2.6.9-xen-sparse/arch/xen/Kconfig
--- xen-2.0/linux-2.6.9-xen-sparse/arch/xen/Kconfig     2004-11-17 
22:51:41.000000000 +0000
+++ xen-2.0-sysrq/linux-2.6.9-xen-sparse/arch/xen/Kconfig       2004-12-08 
15:03:23.000000000 +0000
@@ -164,3 +164,20 @@
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
+
+menu "Kernel hacking"
+
+config MAGIC_SYSRQ
+        bool "Magic SysRq key"
+        help
+          If you say Y here, you will have some control over the system even
+          if the system crashes for example during kernel debugging (e.g., you
+          will be able to flush the buffer cache to disk, reboot the system
+          immediately or dump some status information). This is accomplished
+          by pressing various keys while holding SysRq (Alt+PrintScreen). It
+          also works on a serial console (on PC hardware at least), if you
+          send a BREAK and then within 5 seconds a command keypress. The
+          keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+          unless you really know what this hack does.
+
+endmenu
diff -urN xen-2.0/linux-2.6.9-xen-sparse/arch/xen/kernel/reboot.c 
xen-2.0-sysrq/linux-2.6.9-xen-sparse/arch/xen/kernel/reboot.c
--- xen-2.0/linux-2.6.9-xen-sparse/arch/xen/kernel/reboot.c     2004-11-17 
22:51:41.000000000 +0000
+++ xen-2.0-sysrq/linux-2.6.9-xen-sparse/arch/xen/kernel/reboot.c       
2004-12-08 15:03:23.000000000 +0000
@@ -8,6 +8,7 @@
 #include <linux/unistd.h>
 #include <linux/module.h>
 #include <linux/reboot.h>
+#include <linux/sysrq.h>
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
 #include <asm-xen/ctrl_if.h>
@@ -53,6 +54,7 @@
 
 /* Ignore multiple shutdown requests. */
 static int shutting_down = -1;
+static int pending_sysrq = -1;
 
 static void __do_suspend(void)
 {
@@ -214,9 +216,22 @@
     }
 }
 
+static void __sysrq_handler(void *unused)
+{
+#ifndef CONFIG_MAGIC_SYSRQ
+    printk("CONFIG_MAGIC_SYSRQ not compiled in, will ignore!\n");
+#else
+    handle_sysrq(pending_sysrq, NULL, NULL);
+    pending_sysrq = -1;
+#endif
+}
+
 static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
 {
     static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
+    static DECLARE_WORK(sysrq_work, __sysrq_handler, NULL);
+    
+    printk("msg->subtype = %d, msg->msg[0] = %d", msg->subtype, msg->msg[0]);
 
     if ( (shutting_down == -1) &&
          ((msg->subtype == CMSG_SHUTDOWN_POWEROFF) ||
@@ -226,6 +241,12 @@
         shutting_down = msg->subtype;
         schedule_work(&shutdown_work);
     }
+    else if (msg->subtype == CMSG_SHUTDOWN_SYSRQ)
+    {
+        /* sysrqs are allowed during shutdown in case shutdown stuffs up */
+        pending_sysrq = msg->msg[0];
+        schedule_work(&sysrq_work);
+    }
     else
     {
         printk("Ignore spurious shutdown request\n");
diff -urN xen-2.0/tools/python/xen/xend/XendClient.py 
xen-2.0-sysrq/tools/python/xen/xend/XendClient.py
--- xen-2.0/tools/python/xen/xend/XendClient.py 2004-11-17 22:51:40.000000000 
+0000
+++ xen-2.0-sysrq/tools/python/xen/xend/XendClient.py   2004-12-08 
15:03:23.000000000 +0000
@@ -228,10 +228,11 @@
         return self.xendPost(self.domainurl(id),
                              {'op'      : 'pause' })
 
-    def xend_domain_shutdown(self, id, reason):
+    def xend_domain_shutdown(self, id, reason, key=None):
         return self.xendPost(self.domainurl(id),
                              {'op'      : 'shutdown',
-                              'reason'  : reason })
+                              'reason'  : reason,
+                              'key'     : key })
 
     def xend_domain_destroy(self, id, reason):
         return self.xendPost(self.domainurl(id),
diff -urN xen-2.0/tools/python/xen/xend/XendDomain.py 
xen-2.0-sysrq/tools/python/xen/xend/XendDomain.py
--- xen-2.0/tools/python/xen/xend/XendDomain.py 2004-11-17 22:51:42.000000000 
+0000
+++ xen-2.0-sysrq/tools/python/xen/xend/XendDomain.py   2004-12-09 
10:47:57.000000000 +0000
@@ -455,7 +455,7 @@
         except Exception, ex:
             raise XendError(str(ex))
     
-    def domain_shutdown(self, id, reason='poweroff'):
+    def domain_shutdown(self, id, reason='poweroff', key=None):
         """Shutdown domain (nicely).
          - poweroff: restart according to exit code and restart mode
          - reboot:   restart on exit
@@ -474,7 +474,7 @@
         eserver.inject('xend.domain.shutdown', [dominfo.name, dominfo.id, 
reason])
         if reason == 'halt':
             reason = 'poweroff'
-        val = xend.domain_shutdown(dominfo.id, reason)
+        val = xend.domain_shutdown(dominfo.id, reason, key)
         self.refresh_schedule()
         return val
 
diff -urN xen-2.0/tools/python/xen/xend/server/SrvDaemon.py 
xen-2.0-sysrq/tools/python/xen/xend/server/SrvDaemon.py
--- xen-2.0/tools/python/xen/xend/server/SrvDaemon.py   2004-11-17 
22:51:47.000000000 +0000
+++ xen-2.0-sysrq/tools/python/xen/xend/server/SrvDaemon.py     2004-12-09 
10:51:57.000000000 +0000
@@ -711,14 +711,14 @@
             raise XendError('Invalid console id')
         console.disconnect()
 
-    def domain_shutdown(self, dom, reason):
+    def domain_shutdown(self, dom, reason, key=None):
         """Shutdown a domain.
         """
         dom = int(dom)
         ctrl = self.domainCF.getController(dom)
         if not ctrl:
             raise XendError('No domain controller: %s' % dom)
-        ctrl.shutdown(reason)
+        ctrl.shutdown(reason, key)
         return 0
 
     def domain_mem_target_set(self, dom, target):
diff -urN xen-2.0/tools/python/xen/xend/server/SrvDomain.py 
xen-2.0-sysrq/tools/python/xen/xend/server/SrvDomain.py
--- xen-2.0/tools/python/xen/xend/server/SrvDomain.py   2004-11-17 
22:51:47.000000000 +0000
+++ xen-2.0-sysrq/tools/python/xen/xend/server/SrvDomain.py     2004-12-08 
17:24:07.000000000 +0000
@@ -47,7 +47,8 @@
     def op_shutdown(self, op, req):
         fn = FormFn(self.xd.domain_shutdown,
                     [['dom', 'str'],
-                     ['reason', 'str']])
+                     ['reason', 'str'],
+                     ['key', 'int']])
         val = fn(req.args, {'dom': self.dom.id})
         req.setResponseCode(http.ACCEPTED)
         req.setHeader("Location", "%s/.." % req.prePathURL())
diff -urN xen-2.0/tools/python/xen/xend/server/domain.py 
xen-2.0-sysrq/tools/python/xen/xend/server/domain.py
--- xen-2.0/tools/python/xen/xend/server/domain.py      2004-11-17 
22:51:43.000000000 +0000
+++ xen-2.0-sysrq/tools/python/xen/xend/server/domain.py        2004-12-08 
17:20:02.000000000 +0000
@@ -28,7 +28,8 @@
     """
     reasons = {'poweroff' : 'shutdown_poweroff_t',
                'reboot'   : 'shutdown_reboot_t',
-               'suspend'  : 'shutdown_suspend_t' }
+               'suspend'  : 'shutdown_suspend_t',
+               'sysrq'    : 'shutdown_sysrq_t' }
 
     def __init__(self, factory, dom):
         controller.Controller.__init__(self, factory, dom)
@@ -36,16 +37,19 @@
         self.addMethod(CMSG_MEM_REQUEST, 0, None)
         self.registerChannel()
 
-    def shutdown(self, reason):
+    def shutdown(self, reason, key=None):
         """Shutdown a domain.
 
         reason shutdown reason
+        key    sysrq key (only if reason is 'sysrq')
         """
         msgtype = self.reasons.get(reason)
         if not msgtype:
             raise XendError('invalid reason:' + reason)
-        msg = packMsg(msgtype, {})
-        self.writeRequest(msg)
+        extra = {}
+        if reason == 'sysrq': extra['key'] = key
+        print extra
+        self.writeRequest(packMsg(msgtype, extra))
 
     def mem_target_set(self, target):
         """Set domain memory target in pages.
diff -urN xen-2.0/tools/python/xen/xend/server/messages.py 
xen-2.0-sysrq/tools/python/xen/xend/server/messages.py
--- xen-2.0/tools/python/xen/xend/server/messages.py    2004-11-17 
22:51:42.000000000 +0000
+++ xen-2.0-sysrq/tools/python/xen/xend/server/messages.py      2004-12-08 
15:03:23.000000000 +0000
@@ -197,10 +197,12 @@
 CMSG_SHUTDOWN_POWEROFF  = 0
 CMSG_SHUTDOWN_REBOOT    = 1
 CMSG_SHUTDOWN_SUSPEND   = 2
+CMSG_SHUTDOWN_SYSRQ     = 3
 
 STOPCODE_shutdown       = 0
 STOPCODE_reboot         = 1
 STOPCODE_suspend        = 2
+STOPCODE_sysrq          = 3
 
 shutdown_formats = {
     'shutdown_poweroff_t':
@@ -211,6 +213,9 @@
 
     'shutdown_suspend_t':
     (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
+    
+    'shutdown_sysrq_t':
+    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SYSRQ)
     }
 
 msg_formats.update(shutdown_formats)
diff -urN xen-2.0/tools/python/xen/xm/main.py 
xen-2.0-sysrq/tools/python/xen/xm/main.py
--- xen-2.0/tools/python/xen/xm/main.py 2004-11-17 22:51:47.000000000 +0000
+++ xen-2.0-sysrq/tools/python/xen/xm/main.py   2004-12-08 15:03:23.000000000 
+0000
@@ -11,7 +11,7 @@
 from xen.xend import sxp
 from xen.xend.XendClient import XendError, server
 from xen.xend.XendClient import main as xend_client_main
-from xen.xm import create, destroy, migrate, shutdown
+from xen.xm import create, destroy, migrate, shutdown, sysrq
 from xen.xm.opts import *
 
 class Group:
@@ -401,6 +401,19 @@
 
 xm.prog(ProgShutdown)
 
+class ProgSysrq(Prog):
+    group = 'domain'
+    name = "sysrq"
+    info = """Send a sysrq to a domain."""
+
+    def help(self, args):
+        sysrq.main([args[0], '-h'])
+    
+    def main(self, args):
+        sysrq.main(args)
+
+xm.prog(ProgSysrq)
+
 class ProgPause(Prog):
     group = 'domain'
     name = "pause"
diff -urN xen-2.0/tools/python/xen/xm/sysrq.py 
xen-2.0-sysrq/tools/python/xen/xm/sysrq.py
--- xen-2.0/tools/python/xen/xm/sysrq.py        1970-01-01 01:00:00.000000000 
+0100
+++ xen-2.0-sysrq/tools/python/xen/xm/sysrq.py  2004-12-08 17:17:38.000000000 
+0000
@@ -0,0 +1,39 @@
+# (C) Matthew Bloch <matthew@xxxxxxxxxxxxxx> 2004
+
+"""Domain shutdown.
+"""
+import string
+import sys
+import time
+
+from xen.xend.XendClient import server
+from xen.xm.opts import *
+
+DOM0_NAME = 'Domain-0'
+DOM0_ID = '0'
+
+gopts = Opts(use="""[DOM] [letter]
+
+Sends a Linux sysrq to a domain.
+""")
+
+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)
+    if opts.vals.help:
+        opts.usage()
+        return
+        
+    # no options for the moment
+    if len(args) < 1: opts.err('Missing domain')
+    if len(args) < 2: opts.err('Missing sysrq character')
+    dom = args[0]
+    req = ord(args[1][0])
+    sysrq(dom, req)

 


Rackspace

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