ia64/xen-unstable

changeset 6045:5f6787c5c71f

This patch changes the vcpu-hotplug handler from using control message
over to using xenstore for triggers. Dropping the control messages also
fixes the issue with not being able to use xm vcpu-hotplug on dom0.

Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Aug 06 09:50:51 2005 +0000 (2005-08-06)
parents 968829eb1783
children e0146a206ea2
files linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c tools/python/xen/xend/XendDomainInfo.py
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Sat Aug 06 09:49:22 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Sat Aug 06 09:50:51 2005 +0000
     1.3 @@ -1324,15 +1324,133 @@ void __devinit smp_prepare_boot_cpu(void
     1.4  }
     1.5  
     1.6  #ifdef CONFIG_HOTPLUG_CPU
     1.7 -#include <asm-xen/ctrl_if.h>
     1.8 -
     1.9 +#include <asm-xen/xenbus.h>
    1.10  /* hotplug down/up funtion pointer and target vcpu */
    1.11  struct vcpu_hotplug_handler_t {
    1.12 -	void (*fn)(int vcpu);
    1.13 +	void (*fn) (int vcpu);
    1.14  	u32 vcpu;
    1.15  };
    1.16  static struct vcpu_hotplug_handler_t vcpu_hotplug_handler;
    1.17  
    1.18 +static int vcpu_hotplug_cpu_process(void *unused)
    1.19 +{
    1.20 +	struct vcpu_hotplug_handler_t *handler = &vcpu_hotplug_handler;
    1.21 +
    1.22 +	if (handler->fn) {
    1.23 +		(*(handler->fn)) (handler->vcpu);
    1.24 +		handler->fn = NULL;
    1.25 +	}
    1.26 +	return 0;
    1.27 +}
    1.28 +
    1.29 +static void __vcpu_hotplug_handler(void *unused)
    1.30 +{
    1.31 +	int err;
    1.32 +
    1.33 +	err = kernel_thread(vcpu_hotplug_cpu_process,
    1.34 +			    NULL, CLONE_FS | CLONE_FILES);
    1.35 +	if (err < 0)
    1.36 +		printk(KERN_ALERT "Error creating hotplug_cpu process!\n");
    1.37 +}
    1.38 +
    1.39 +static void handle_cpus_watch(struct xenbus_watch *, const char *);
    1.40 +static struct notifier_block xsn_cpus;
    1.41 +
    1.42 +/* xenbus watch struct */
    1.43 +static struct xenbus_watch cpus_watch = {
    1.44 +	.node = "cpus",
    1.45 +	.callback = handle_cpus_watch,
    1.46 +};
    1.47 +
    1.48 +static int setup_cpus_watcher(struct notifier_block *notifier,
    1.49 +			      unsigned long event, void *data)
    1.50 +{
    1.51 +	int err = 0;
    1.52 +
    1.53 +	down(&xenbus_lock);
    1.54 +	err = register_xenbus_watch(&cpus_watch);
    1.55 +	up(&xenbus_lock);
    1.56 +
    1.57 +	if (err) {
    1.58 +		printk("Failed to set cpus watcher\n");
    1.59 +	}
    1.60 +	return NOTIFY_DONE;
    1.61 +}
    1.62 +
    1.63 +static void handle_cpus_watch(struct xenbus_watch *watch, const char *node)
    1.64 +{
    1.65 +	static DECLARE_WORK(vcpu_hotplug_work, __vcpu_hotplug_handler, NULL);
    1.66 +	struct vcpu_hotplug_handler_t *handler = &vcpu_hotplug_handler;
    1.67 +	ssize_t ret;
    1.68 +	int err, cpu, state;
    1.69 +	char dir[32];
    1.70 +	char *cpustr;
    1.71 +
    1.72 +	/* get a pointer to start of cpus/cpu string */
    1.73 +	if ((cpustr = strstr(node, "cpus/cpu")) != NULL) {
    1.74 +
    1.75 +		/* find which cpu state changed, note vcpu for handler */
    1.76 +		sscanf(cpustr, "cpus/cpu%d", &cpu);
    1.77 +		handler->vcpu = cpu;
    1.78 +
    1.79 +		/* calc the dir for xenbus read */
    1.80 +		sprintf(dir, "cpus/cpu%d", cpu);
    1.81 +
    1.82 +		/* make sure watch that was triggered is changes to the online key */
    1.83 +		if ((strcmp(node + strlen(dir), "/online")) != 0)
    1.84 +			return;
    1.85 +
    1.86 +		/* get the state value */
    1.87 +		xenbus_transaction_start("cpus");
    1.88 +		err = xenbus_scanf(dir, "online", "%d", &state);
    1.89 +		xenbus_transaction_end(0);
    1.90 +
    1.91 +		if (err != 1) {
    1.92 +			printk(KERN_ERR
    1.93 +			       "XENBUS: Unable to read cpu online state\n");
    1.94 +			return;
    1.95 +		}
    1.96 +
    1.97 +		/* if we detect a state change, take action */
    1.98 +		switch (state) {
    1.99 +			/* offline -> online */
   1.100 +		case 1:
   1.101 +			if (!cpu_isset(cpu, cpu_online_map)) {
   1.102 +				handler->fn = (void *)&cpu_up;
   1.103 +				ret = schedule_work(&vcpu_hotplug_work);
   1.104 +			}
   1.105 +			break;
   1.106 +			/* online -> offline */
   1.107 +		case 0:
   1.108 +			if (cpu_isset(cpu, cpu_online_map)) {
   1.109 +				handler->fn = (void *)&cpu_down;
   1.110 +				ret = schedule_work(&vcpu_hotplug_work);
   1.111 +			}
   1.112 +			break;
   1.113 +		default:
   1.114 +			printk(KERN_ERR
   1.115 +			       "XENBUS: unknown state(%d) on node(%s)\n", state,
   1.116 +			       node);
   1.117 +		}
   1.118 +	}
   1.119 +	return;
   1.120 +}
   1.121 +
   1.122 +static int __init setup_vcpu_hotplug_event(void)
   1.123 +{
   1.124 +	xsn_cpus.notifier_call = setup_cpus_watcher;
   1.125 +
   1.126 +	if (xen_start_info.store_evtchn) {
   1.127 +		setup_cpus_watcher(&xsn_cpus, 0, NULL);
   1.128 +	} else {
   1.129 +		register_xenstore_notifier(&xsn_cpus);
   1.130 +	}
   1.131 +
   1.132 +	return 0;
   1.133 +}
   1.134 +
   1.135 +subsys_initcall(setup_vcpu_hotplug_event);
   1.136 +
   1.137  /* must be called with the cpucontrol mutex held */
   1.138  static int __devinit cpu_enable(unsigned int cpu)
   1.139  {
   1.140 @@ -1401,77 +1519,6 @@ void __cpu_die(unsigned int cpu)
   1.141   	printk(KERN_ERR "CPU %u didn't die...\n", cpu);
   1.142  }
   1.143  
   1.144 -static int vcpu_hotplug_cpu_process(void *unused)
   1.145 -{
   1.146 -	struct vcpu_hotplug_handler_t *handler = &vcpu_hotplug_handler;
   1.147 -
   1.148 -	if (handler->fn) {
   1.149 -		(*(handler->fn))(handler->vcpu);
   1.150 -		handler->fn = NULL;
   1.151 -	}
   1.152 -	return 0;
   1.153 -}
   1.154 -
   1.155 -static void __vcpu_hotplug_handler(void *unused)
   1.156 -{
   1.157 -	int err;
   1.158 -
   1.159 -	err = kernel_thread(vcpu_hotplug_cpu_process, 
   1.160 -			    NULL, CLONE_FS | CLONE_FILES);
   1.161 -	if (err < 0)
   1.162 -		printk(KERN_ALERT "Error creating hotplug_cpu process!\n");
   1.163 -
   1.164 -}
   1.165 -
   1.166 -static void vcpu_hotplug_event_handler(ctrl_msg_t *msg, unsigned long id)
   1.167 -{
   1.168 -	static DECLARE_WORK(vcpu_hotplug_work, __vcpu_hotplug_handler, NULL);
   1.169 -	vcpu_hotplug_t *req = (vcpu_hotplug_t *)&msg->msg[0];
   1.170 -	struct vcpu_hotplug_handler_t *handler = &vcpu_hotplug_handler;
   1.171 -	ssize_t ret;
   1.172 -
   1.173 -	if (msg->length != sizeof(vcpu_hotplug_t))
   1.174 -		goto parse_error;
   1.175 -
   1.176 -	/* grab target vcpu from msg */
   1.177 -	handler->vcpu = req->vcpu;
   1.178 -
   1.179 -	/* determine which function to call based on msg subtype */
   1.180 -	switch (msg->subtype) {
   1.181 -        case CMSG_VCPU_HOTPLUG_OFF:
   1.182 -		handler->fn = (void *)&cpu_down;
   1.183 -		ret = schedule_work(&vcpu_hotplug_work);
   1.184 -		req->status = (u32) ret;
   1.185 -		break;
   1.186 -        case CMSG_VCPU_HOTPLUG_ON:
   1.187 -		handler->fn = (void *)&cpu_up;
   1.188 -		ret = schedule_work(&vcpu_hotplug_work);
   1.189 -		req->status = (u32) ret;
   1.190 -		break;
   1.191 -        default:
   1.192 -		goto parse_error;
   1.193 -	}
   1.194 -
   1.195 -	ctrl_if_send_response(msg);
   1.196 -	return;
   1.197 - parse_error:
   1.198 -	msg->length = 0;
   1.199 -	ctrl_if_send_response(msg);
   1.200 -}
   1.201 -
   1.202 -static int __init setup_vcpu_hotplug_event(void)
   1.203 -{
   1.204 -	struct vcpu_hotplug_handler_t *handler = &vcpu_hotplug_handler;
   1.205 -
   1.206 -	handler->fn = NULL;
   1.207 -	ctrl_if_register_receiver(CMSG_VCPU_HOTPLUG,
   1.208 -				  vcpu_hotplug_event_handler, 0);
   1.209 -
   1.210 -	return 0;
   1.211 -}
   1.212 -
   1.213 -__initcall(setup_vcpu_hotplug_event);
   1.214 -
   1.215  #else /* ... !CONFIG_HOTPLUG_CPU */
   1.216  int __cpu_disable(void)
   1.217  {
     2.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Sat Aug 06 09:49:22 2005 +0000
     2.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Sat Aug 06 09:50:51 2005 +0000
     2.3 @@ -258,6 +258,7 @@ class XendDomainInfo:
     2.4          self.restart_count = 0
     2.5          
     2.6          self.vcpus = 1
     2.7 +        self.vcpusdb = {}
     2.8          self.bootloader = None
     2.9  
    2.10      def setDB(self, db):
    2.11 @@ -539,6 +540,16 @@ class XendDomainInfo:
    2.12          except:
    2.13              raise VmError('invalid vcpus value')
    2.14  
    2.15 +    def exportVCPUSToDB(self, vcpus):
    2.16 +        for v in range(0,vcpus):
    2.17 +            path = "/cpus/cpu%d"%(v)
    2.18 +            if not self.vcpusdb.has_key(path):
    2.19 +                self.vcpusdb[path] = self.db.addChild(path)
    2.20 +            db = self.vcpusdb[path]
    2.21 +            log.debug("writing key online=1 to path %s in store"%(path))
    2.22 +            db['online'] = "1"
    2.23 +            db.saveDB(save=True)
    2.24 +
    2.25      def init_image(self):
    2.26          """Create boot image handler for the domain.
    2.27          """
    2.28 @@ -557,6 +568,8 @@ class XendDomainInfo:
    2.29              self.db.introduceDomain(self.id,
    2.30                                      self.store_mfn,
    2.31                                      self.store_channel)
    2.32 +        # get the configured value of vcpus and update store
    2.33 +        self.exportVCPUSToDB(self.vcpus)
    2.34  
    2.35      def delete(self):
    2.36          """Delete the vm's db.
    2.37 @@ -921,14 +934,20 @@ class XendDomainInfo:
    2.38      def vcpu_hotplug(self, vcpu, state):
    2.39          """Disable or enable VCPU in domain.
    2.40          """
    2.41 -        log.error("Holly Shit! %d %d\n" % (vcpu, state))
    2.42 -        if self.channel:
    2.43 +        db = ""
    2.44 +        try:
    2.45 +            db = self.vcpusdb['/cpus/cpu%d'%(vcpu)]
    2.46 +        except:
    2.47 +            log.error("Invalid VCPU")
    2.48 +            return
    2.49 +
    2.50 +        if self.store_channel:
    2.51              if int(state) == 0:
    2.52 -                msg = messages.packMsg('vcpu_hotplug_off_t', { 'vcpu' : vcpu} )
    2.53 +                db['online'] = "0"
    2.54              else:
    2.55 -                msg = messages.packMsg('vcpu_hotplug_on_t',  { 'vcpu' : vcpu} )
    2.56 +                db['online'] = "1"
    2.57  
    2.58 -            self.channel.writeRequest(msg)
    2.59 +        db.saveDB(save=True)
    2.60  
    2.61      def shutdown(self, reason):
    2.62          if not reason in shutdown_reasons.values():
    2.63 @@ -957,6 +976,8 @@ class XendDomainInfo:
    2.64              self.db.introduceDomain(self.id, self.store_mfn,
    2.65                                      self.store_channel)
    2.66          self.exportToDB(save=True, sync=True)
    2.67 +        # get run-time value of vcpus and update store
    2.68 +        self.exportVCPUSToDB(dom_get(self.id)['vcpus'])
    2.69  
    2.70  def vm_field_ignore(vm, config, val, index):
    2.71      """Dummy config field handler used for fields with built-in handling.