ia64/xen-unstable

changeset 6034:38e6467df0e6

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@us.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Aug 05 08:59:41 2005 +0000 (2005-08-05)
parents 61cbf8f977ef
children f5a5e61f038e
files linux-2.6-xen-sparse/arch/xen/kernel/reboot.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c linux-2.6-xen-sparse/include/asm-xen/xenbus.h tools/python/xen/xend/XendClient.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xm/sysrq.py
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Thu Aug 04 18:51:55 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Fri Aug 05 08:59:41 2005 +0000
     1.3 @@ -11,7 +11,6 @@ static int errno;
     1.4  #include <linux/sysrq.h>
     1.5  #include <asm/irq.h>
     1.6  #include <asm/mmu_context.h>
     1.7 -#include <asm-xen/ctrl_if.h>
     1.8  #include <asm-xen/evtchn.h>
     1.9  #include <asm-xen/hypervisor.h>
    1.10  #include <asm-xen/xen-public/dom0_ops.h>
    1.11 @@ -19,6 +18,11 @@ static int errno;
    1.12  #include <asm-xen/queues.h>
    1.13  #include <asm-xen/xenbus.h>
    1.14  
    1.15 +#define SHUTDOWN_INVALID  -1
    1.16 +#define SHUTDOWN_POWEROFF  0
    1.17 +#define SHUTDOWN_REBOOT    1
    1.18 +#define SHUTDOWN_SUSPEND   2
    1.19 +
    1.20  void machine_restart(char * __unused)
    1.21  {
    1.22  	/* We really want to get pending console data out before we die. */
    1.23 @@ -53,7 +57,7 @@ EXPORT_SYMBOL(machine_power_off);
    1.24   */
    1.25  
    1.26  /* Ignore multiple shutdown requests. */
    1.27 -static int shutting_down = -1;
    1.28 +static int shutting_down = SHUTDOWN_INVALID;
    1.29  
    1.30  static void __do_suspend(void)
    1.31  {
    1.32 @@ -126,8 +130,6 @@ static void __do_suspend(void)
    1.33  
    1.34      xenbus_suspend();
    1.35  
    1.36 -    ctrl_if_suspend();
    1.37 -
    1.38      irq_suspend();
    1.39  
    1.40      gnttab_suspend();
    1.41 @@ -140,7 +142,7 @@ static void __do_suspend(void)
    1.42  
    1.43      HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
    1.44  
    1.45 -    shutting_down = -1; 
    1.46 +    shutting_down = SHUTDOWN_INVALID; 
    1.47  
    1.48      memcpy(&xen_start_info, &suspend_record->resume_info,
    1.49             sizeof(xen_start_info));
    1.50 @@ -163,8 +165,6 @@ static void __do_suspend(void)
    1.51  
    1.52      irq_resume();
    1.53  
    1.54 -    ctrl_if_resume();
    1.55 -
    1.56      xenbus_resume();
    1.57  
    1.58  #ifdef CONFIG_SMP
    1.59 @@ -204,7 +204,7 @@ static int shutdown_process(void *__unus
    1.60  
    1.61      switch ( shutting_down )
    1.62      {
    1.63 -    case CMSG_SHUTDOWN_POWEROFF:
    1.64 +    case SHUTDOWN_POWEROFF:
    1.65          if ( execve("/sbin/poweroff", poweroff_argv, envp) < 0 )
    1.66          {
    1.67              sys_reboot(LINUX_REBOOT_MAGIC1,
    1.68 @@ -214,7 +214,7 @@ static int shutdown_process(void *__unus
    1.69          }
    1.70          break;
    1.71  
    1.72 -    case CMSG_SHUTDOWN_REBOOT:
    1.73 +    case SHUTDOWN_REBOOT:
    1.74          if ( execve("/sbin/reboot", restart_argv, envp) < 0 )
    1.75          {
    1.76              sys_reboot(LINUX_REBOOT_MAGIC1,
    1.77 @@ -225,7 +225,7 @@ static int shutdown_process(void *__unus
    1.78          break;
    1.79      }
    1.80  
    1.81 -    shutting_down = -1; /* could try again */
    1.82 +    shutting_down = SHUTDOWN_INVALID; /* could try again */
    1.83  
    1.84      return 0;
    1.85  }
    1.86 @@ -234,7 +234,7 @@ static void __shutdown_handler(void *unu
    1.87  {
    1.88      int err;
    1.89  
    1.90 -    if ( shutting_down != CMSG_SHUTDOWN_SUSPEND )
    1.91 +    if ( shutting_down != SHUTDOWN_SUSPEND )
    1.92      {
    1.93          err = kernel_thread(shutdown_process, NULL, CLONE_FS | CLONE_FILES);
    1.94          if ( err < 0 )
    1.95 @@ -246,42 +246,103 @@ static void __shutdown_handler(void *unu
    1.96      }
    1.97  }
    1.98  
    1.99 -static void shutdown_handler(ctrl_msg_t *msg, unsigned long id)
   1.100 +static void shutdown_handler(struct xenbus_watch *watch, const char *node)
   1.101  {
   1.102      static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
   1.103  
   1.104 -    if ( msg->subtype == CMSG_SHUTDOWN_SYSRQ )
   1.105 -    {
   1.106 -	int sysrq = ((shutdown_sysrq_t *)&msg->msg[0])->key;
   1.107 -	
   1.108 +    int type = -1;
   1.109 +
   1.110 +    if (!xenbus_scanf("control", "shutdown", "%i", &type)) {
   1.111 +        printk("Unable to read code in control/shutdown\n");
   1.112 +        return;
   1.113 +    };
   1.114 +
   1.115 +    xenbus_printf("control", "shutdown", "%i", SHUTDOWN_INVALID);
   1.116 +
   1.117 +    if ((type == SHUTDOWN_POWEROFF) ||
   1.118 +        (type == SHUTDOWN_REBOOT)   ||
   1.119 +        (type == SHUTDOWN_SUSPEND)) {
   1.120 +        shutting_down = type;
   1.121 +        schedule_work(&shutdown_work);
   1.122 +    }
   1.123 +
   1.124 +}
   1.125 +
   1.126  #ifdef CONFIG_MAGIC_SYSRQ
   1.127 +static void sysrq_handler(struct xenbus_watch *watch, const char *node)
   1.128 +{
   1.129 +    char sysrq_key = '\0';
   1.130 +    
   1.131 +    if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) {
   1.132 +        printk("Unable to read sysrq code in control/sysrq\n");
   1.133 +        return;
   1.134 +    }
   1.135 +
   1.136 +    xenbus_printf("control", "sysrq", "%c", '\0');
   1.137 +
   1.138 +    if (sysrq_key != '\0') {
   1.139 +
   1.140  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   1.141 -	handle_sysrq(sysrq, NULL, NULL);
   1.142 +        handle_sysrq(sysrq_key, NULL, NULL);
   1.143  #else
   1.144 -	handle_sysrq(sysrq, NULL, NULL, NULL);
   1.145 -#endif
   1.146 +        handle_sysrq(sysrq_key, NULL, NULL, NULL);
   1.147  #endif
   1.148      }
   1.149 -    else if ( (shutting_down == -1) &&
   1.150 -         ((msg->subtype == CMSG_SHUTDOWN_POWEROFF) ||
   1.151 -          (msg->subtype == CMSG_SHUTDOWN_REBOOT) ||
   1.152 -          (msg->subtype == CMSG_SHUTDOWN_SUSPEND)) )
   1.153 -    {
   1.154 -        shutting_down = msg->subtype;
   1.155 -        schedule_work(&shutdown_work);
   1.156 +}
   1.157 +#endif
   1.158 +
   1.159 +static struct xenbus_watch shutdown_watch = {
   1.160 +    .node = "control/shutdown",
   1.161 +    .callback = shutdown_handler
   1.162 +};
   1.163 +
   1.164 +#ifdef CONFIG_MAGIC_SYSRQ
   1.165 +static struct xenbus_watch sysrq_watch = {
   1.166 +    .node ="control/sysrq",
   1.167 +    .callback = sysrq_handler
   1.168 +};
   1.169 +#endif
   1.170 +
   1.171 +static struct notifier_block xenstore_notifier;
   1.172 +
   1.173 +static int setup_shutdown_watcher(struct notifier_block *notifier,
   1.174 +                                  unsigned long event,
   1.175 +                                  void *data)
   1.176 +{
   1.177 +    int err1=0, err2=0;
   1.178 +
   1.179 +    down(&xenbus_lock);
   1.180 +    err1 = register_xenbus_watch(&shutdown_watch);
   1.181 +#ifdef CONFIG_MAGIC_SYSRQ
   1.182 +    err2 = register_xenbus_watch(&sysrq_watch);
   1.183 +#endif
   1.184 +    up(&xenbus_lock);
   1.185 +
   1.186 +    if (err1) {
   1.187 +        printk("Failed to set shutdown watcher\n");
   1.188      }
   1.189 -    else
   1.190 -    {
   1.191 -        printk("Ignore spurious shutdown request\n");
   1.192 +    
   1.193 +#ifdef CONFIG_MAGIC_SYSRQ
   1.194 +    if (err2) {
   1.195 +        printk("Failed to set sysrq watcher\n");
   1.196      }
   1.197 +#endif
   1.198  
   1.199 -    ctrl_if_send_response(msg);
   1.200 +    return NOTIFY_STOP;
   1.201  }
   1.202  
   1.203  static int __init setup_shutdown_event(void)
   1.204  {
   1.205 -    ctrl_if_register_receiver(CMSG_SHUTDOWN, shutdown_handler, 0);
   1.206 +    
   1.207 +    xenstore_notifier.notifier_call = setup_shutdown_watcher;
   1.208 +
   1.209 +    if (xen_start_info.store_evtchn) {
   1.210 +        setup_shutdown_watcher(&xenstore_notifier, 0, NULL);
   1.211 +    } else {
   1.212 +        register_xenstore_notifier(&xenstore_notifier);
   1.213 +    }
   1.214 +    
   1.215      return 0;
   1.216  }
   1.217  
   1.218 -__initcall(setup_shutdown_event);
   1.219 +subsys_initcall(setup_shutdown_event);
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Thu Aug 04 18:51:55 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Fri Aug 05 08:59:41 2005 +0000
     2.3 @@ -36,10 +36,16 @@
     2.4  #include <linux/ctype.h>
     2.5  #include <linux/fcntl.h>
     2.6  #include <stdarg.h>
     2.7 +#include <linux/notifier.h>
     2.8  #include "xenbus_comms.h"
     2.9  
    2.10  #define streq(a, b) (strcmp((a), (b)) == 0)
    2.11  
    2.12 +/* Protects notifier chain */
    2.13 +DECLARE_MUTEX(xenstore_control);
    2.14 +
    2.15 +static struct notifier_block *xenstore_chain;
    2.16 +
    2.17  /* If something in array of ids matches this device, return it. */
    2.18  static const struct xenbus_device_id *
    2.19  match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
    2.20 @@ -309,6 +315,26 @@ void xenbus_resume(void)
    2.21  	up(&xenbus_lock);
    2.22  }
    2.23  
    2.24 +int register_xenstore_notifier(struct notifier_block *nb)
    2.25 +{
    2.26 +	int ret;
    2.27 +
    2.28 +	if ((ret = down_interruptible(&xenstore_control)) != 0) 
    2.29 +		return ret;
    2.30 +	ret = notifier_chain_register(&xenstore_chain, nb);
    2.31 +	up(&xenstore_control);
    2.32 +	return ret;
    2.33 +}
    2.34 +EXPORT_SYMBOL(register_xenstore_notifier);
    2.35 +
    2.36 +void unregister_xenstore_notifier(struct notifier_block *nb)
    2.37 +{
    2.38 +	down(&xenstore_control);
    2.39 +	notifier_chain_unregister(&xenstore_chain, nb);
    2.40 +	up(&xenstore_control);
    2.41 +}
    2.42 +EXPORT_SYMBOL(unregister_xenstore_notifier);
    2.43 +
    2.44  /* called from a thread in privcmd/privcmd.c */
    2.45  int do_xenbus_probe(void *unused)
    2.46  {
    2.47 @@ -323,6 +349,15 @@ int do_xenbus_probe(void *unused)
    2.48  		return err;
    2.49  	}
    2.50  
    2.51 +	err = notifier_call_chain(&xenstore_chain, 0, 0);
    2.52 +	if (err == NOTIFY_BAD) {
    2.53 +		printk("%s: calling xenstore notify chain failed\n",
    2.54 +		       __FUNCTION__);
    2.55 +		return -EINVAL;
    2.56 +	}
    2.57 +
    2.58 +	err = 0;
    2.59 +
    2.60  	/* Initialize non-xenbus drivers */
    2.61  	balloon_init_watcher();
    2.62  
     3.1 --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h	Thu Aug 04 18:51:55 2005 +0000
     3.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h	Fri Aug 05 08:59:41 2005 +0000
     3.3 @@ -29,6 +29,7 @@
     3.4   * IN THE SOFTWARE.
     3.5   */
     3.6  #include <linux/device.h>
     3.7 +#include <linux/notifier.h>
     3.8  #include <asm/semaphore.h>
     3.9  
    3.10  /* A xenbus device. */
    3.11 @@ -112,6 +113,10 @@ struct xenbus_watch
    3.12  	void (*callback)(struct xenbus_watch *, const char *node);
    3.13  };
    3.14  
    3.15 +/* notifer routines for when the xenstore comes up */
    3.16 +int register_xenstore_notifier(struct notifier_block *nb);
    3.17 +void unregister_xenstore_notifier(struct notifier_block *nb);
    3.18 +
    3.19  int register_xenbus_watch(struct xenbus_watch *watch);
    3.20  void unregister_xenbus_watch(struct xenbus_watch *watch);
    3.21  
     4.1 --- a/tools/python/xen/xend/XendClient.py	Thu Aug 04 18:51:55 2005 +0000
     4.2 +++ b/tools/python/xen/xend/XendClient.py	Fri Aug 05 08:59:41 2005 +0000
     4.3 @@ -208,11 +208,15 @@ class Xend:
     4.4          return self.xendPost(self.domainurl(id),
     4.5                               {'op'      : 'pause' })
     4.6  
     4.7 -    def xend_domain_shutdown(self, id, reason, key=0):
     4.8 +    def xend_domain_shutdown(self, id, reason):
     4.9          return self.xendPost(self.domainurl(id),
    4.10                               {'op'      : 'shutdown',
    4.11 -                              'reason'  : reason,
    4.12 -                              'key'     : key })
    4.13 +                              'reason'  : reason})
    4.14 +
    4.15 +    def xend_domain_sysrq(self, id, key):
    4.16 +        return self.xendPost(self.domainurl(id),
    4.17 +                             {'op'      : 'sysrq',
    4.18 +                              'key'     : key})
    4.19  
    4.20      def xend_domain_destroy(self, id, reason):
    4.21          return self.xendPost(self.domainurl(id),
     5.1 --- a/tools/python/xen/xend/XendDomain.py	Thu Aug 04 18:51:55 2005 +0000
     5.2 +++ b/tools/python/xen/xend/XendDomain.py	Fri Aug 05 08:59:41 2005 +0000
     5.3 @@ -386,7 +386,7 @@ class XendDomain:
     5.4          except Exception, ex:
     5.5              raise XendError(str(ex))
     5.6      
     5.7 -    def domain_shutdown(self, id, reason='poweroff', key=0):
     5.8 +    def domain_shutdown(self, id, reason='poweroff'):
     5.9          """Shutdown domain (nicely).
    5.10           - poweroff: restart according to exit code and restart mode
    5.11           - reboot:   restart on exit
    5.12 @@ -402,11 +402,18 @@ class XendDomain:
    5.13          eserver.inject('xend.domain.shutdown', [dominfo.name, dominfo.id, reason])
    5.14          if reason == 'halt':
    5.15              reason = 'poweroff'
    5.16 -        val = dominfo.shutdown(reason, key=key)
    5.17 -        if not reason in ['suspend', 'sysrq']:
    5.18 +        val = dominfo.shutdown(reason)
    5.19 +        if not reason in ['suspend']:
    5.20              self.domain_shutdowns()
    5.21          return val
    5.22  
    5.23 +    def domain_sysrq(self, id, key):
    5.24 +        """Send a SysRq to a domain
    5.25 +        """
    5.26 +        dominfo = self.domain_lookup(id)
    5.27 +        val = dominfo.send_sysrq(key)
    5.28 +        return val
    5.29 +
    5.30      def domain_shutdowns(self):
    5.31          """Process pending domain shutdowns.
    5.32          Destroys domains whose shutdowns have timed out.
     6.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Thu Aug 04 18:51:55 2005 +0000
     6.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Fri Aug 05 08:59:41 2005 +0000
     6.3 @@ -52,13 +52,12 @@ shutdown_reasons = {
     6.4      DOMAIN_CRASH   : "crash",
     6.5      }
     6.6  
     6.7 -"""Map shutdown reasons to the message type to use.
     6.8 +"""Map shutdown reasons to codes
     6.9  """
    6.10 -shutdown_messages = {
    6.11 -    'poweroff' : 'shutdown_poweroff_t',
    6.12 -    'reboot'   : 'shutdown_reboot_t',
    6.13 -    'suspend'  : 'shutdown_suspend_t',
    6.14 -    'sysrq'    : 'shutdown_sysrq_t',
    6.15 +shutdown_codes = {
    6.16 +    'poweroff' : DOMAIN_POWEROFF,
    6.17 +    'reboot'   : DOMAIN_REBOOT,
    6.18 +    'suspend'  : DOMAIN_SUSPEND,
    6.19      }
    6.20  
    6.21  RESTART_ALWAYS   = 'always'
    6.22 @@ -152,8 +151,6 @@ class XendDomainInfo:
    6.23          vm = cls(db)
    6.24          vm.construct(config)
    6.25          vm.saveToDB(sync=True)
    6.26 -        # Flush info to xenstore immediately
    6.27 -        vm.exportToDB()
    6.28  
    6.29          return vm
    6.30  
    6.31 @@ -941,19 +938,20 @@ class XendDomainInfo:
    6.32  
    6.33              self.channel.writeRequest(msg)
    6.34  
    6.35 -    def shutdown(self, reason, key=0):
    6.36 -        msgtype = shutdown_messages.get(reason)
    6.37 -        if not msgtype:
    6.38 +    def shutdown(self, reason):
    6.39 +        reasonid = shutdown_codes.get(reason)
    6.40 +        if reasonid == None:
    6.41              raise XendError('invalid reason:' + reason)
    6.42 -        extra = {}
    6.43 -        if reason == 'sysrq':
    6.44 -            extra['key'] = key
    6.45 -        if self.channel:
    6.46 -            msg = messages.packMsg(msgtype, extra)
    6.47 -            self.channel.writeRequest(msg)
    6.48 -        if not reason in ['suspend', 'sysrq']:
    6.49 -            self.shutdown_pending = {'start':time.time(), 'reason':reason,
    6.50 -                                     'key':key}
    6.51 +        db = self.db.addChild("/control");
    6.52 +        db['shutdown'] = '%i' % reasonid;
    6.53 +        db.saveDB(save=True);
    6.54 +        if not reason in ['suspend']:
    6.55 +            self.shutdown_pending = {'start':time.time(), 'reason':reason}
    6.56 +
    6.57 +    def send_sysrq(self, key=0):
    6.58 +        db = self.db.addChild("/control");
    6.59 +        db['sysrq'] = '%c' % key;
    6.60 +        db.saveDB(save=True);        
    6.61  
    6.62      def shutdown_time_left(self, timeout):
    6.63          if not self.shutdown_pending:
     7.1 --- a/tools/python/xen/xend/server/SrvDomain.py	Thu Aug 04 18:51:55 2005 +0000
     7.2 +++ b/tools/python/xen/xend/server/SrvDomain.py	Fri Aug 05 08:59:41 2005 +0000
     7.3 @@ -39,9 +39,17 @@ class SrvDomain(SrvDir):
     7.4      def op_shutdown(self, op, req):
     7.5          fn = FormFn(self.xd.domain_shutdown,
     7.6                      [['dom',    'int'],
     7.7 -                     ['reason', 'str'],
     7.8 +                     ['reason', 'str']])
     7.9 +        val = fn(req.args, {'dom': self.dom.id})
    7.10 +        req.setResponseCode(http.ACCEPTED)
    7.11 +        req.setHeader("Location", "%s/.." % req.prePathURL())
    7.12 +        return val
    7.13 +
    7.14 +    def op_sysrq(self, op, req):
    7.15 +        fn = FormFn(self.xd.domain_sysrq,
    7.16 +                    [['dom',    'int'],
    7.17                       ['key',    'int']])
    7.18 -        val = fn(req.args, {'dom': self.dom.id})
    7.19 +        val = fn(req.args, {'dom' : self.dom.id})
    7.20          req.setResponseCode(http.ACCEPTED)
    7.21          req.setHeader("Location", "%s/.." % req.prePathURL())
    7.22          return val
     8.1 --- a/tools/python/xen/xm/sysrq.py	Thu Aug 04 18:51:55 2005 +0000
     8.2 +++ b/tools/python/xen/xm/sysrq.py	Fri Aug 05 08:59:41 2005 +0000
     8.3 @@ -21,9 +21,6 @@ gopts.opt('help', short='h',
     8.4           fn=set_true, default=0,
     8.5           use="Print this help.")
     8.6  
     8.7 -def sysrq(dom, req):
     8.8 -    server.xend_domain_shutdown(dom, 'sysrq', req)
     8.9 -
    8.10  def main(argv):
    8.11      opts = gopts
    8.12      args = opts.parse(argv)
    8.13 @@ -36,4 +33,4 @@ def main(argv):
    8.14      if len(args) < 2: opts.err('Missing sysrq character')
    8.15      dom = args[0]
    8.16      req = ord(args[1][0])
    8.17 -    sysrq(dom, req)
    8.18 +    server.xend_domain_sysrq(dom, req)