ia64/xen-unstable

changeset 14178:1ec0d322402e

More PV save/restore fixes.

Related changesets:
14148:b67c253d1cdb4f502dec2
13519:b4a8000e76db6b4b27341

These three changesets must be applied as a set!

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Wed Feb 28 14:13:09 2007 +0000 (2007-02-28)
parents 0f0ac445bf82
children aac0a4b8e328
files linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c tools/python/xen/xend/XendCheckpoint.py tools/xenstore/xenstored_domain.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c	Wed Feb 28 13:22:20 2007 +0000
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c	Wed Feb 28 14:13:09 2007 +0000
     1.3 @@ -137,12 +137,15 @@ int xb_write(const void *data, unsigned 
     1.4  	return 0;
     1.5  }
     1.6  
     1.7 -int xb_wait_for_data_to_read(void)
     1.8 +int xb_data_to_read(void)
     1.9  {
    1.10  	struct xenstore_domain_interface *intf = xen_store_interface;
    1.11 -	return wait_event_interruptible(
    1.12 -		xb_waitq,
    1.13 -		intf->rsp_cons != intf->rsp_prod);
    1.14 +	return (intf->rsp_cons != intf->rsp_prod);
    1.15 +}
    1.16 +
    1.17 +int xb_wait_for_data_to_read(void)
    1.18 +{
    1.19 +	return wait_event_interruptible(xb_waitq, xb_data_to_read());
    1.20  }
    1.21  
    1.22  int xb_read(void *data, unsigned len)
    1.23 @@ -197,8 +200,20 @@ int xb_read(void *data, unsigned len)
    1.24  /* Set up interrupt handler off store event channel. */
    1.25  int xb_init_comms(void)
    1.26  {
    1.27 +	struct xenstore_domain_interface *intf = xen_store_interface;
    1.28  	int err;
    1.29  
    1.30 +	if (intf->req_prod != intf->req_cons)
    1.31 +		printk(KERN_ERR "XENBUS request ring is not quiescent "
    1.32 +		       "(%08x:%08x)!\n", intf->req_cons, intf->req_prod);
    1.33 +
    1.34 +	if (intf->rsp_prod != intf->rsp_cons) {
    1.35 +		printk(KERN_WARNING "XENBUS response ring is not quiescent "
    1.36 +		       "(%08x:%08x): fixing up\n",
    1.37 +		       intf->rsp_cons, intf->rsp_prod);
    1.38 +		intf->rsp_cons = intf->rsp_prod;
    1.39 +	}
    1.40 +
    1.41  	if (xenbus_irq)
    1.42  		unbind_from_irqhandler(xenbus_irq, &xb_waitq);
    1.43  
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h	Wed Feb 28 13:22:20 2007 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h	Wed Feb 28 14:13:09 2007 +0000
     2.3 @@ -37,6 +37,7 @@ int xb_init_comms(void);
     2.4  /* Low level routines. */
     2.5  int xb_write(const void *data, unsigned len);
     2.6  int xb_read(void *data, unsigned len);
     2.7 +int xb_data_to_read(void);
     2.8  int xb_wait_for_data_to_read(void);
     2.9  int xs_input_avail(void);
    2.10  extern struct xenstore_domain_interface *xen_store_interface;
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Wed Feb 28 13:22:20 2007 +0000
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Wed Feb 28 14:13:09 2007 +0000
     3.3 @@ -80,6 +80,9 @@ struct xs_handle {
     3.4  	/* One request at a time. */
     3.5  	struct mutex request_mutex;
     3.6  
     3.7 +	/* Protect xenbus reader thread against save/restore. */
     3.8 +	struct mutex response_mutex;
     3.9 +
    3.10  	/* Protect transactions against save/restore. */
    3.11  	struct rw_semaphore suspend_mutex;
    3.12  };
    3.13 @@ -654,6 +657,7 @@ void xs_suspend(void)
    3.14  {
    3.15  	down_write(&xs_state.suspend_mutex);
    3.16  	mutex_lock(&xs_state.request_mutex);
    3.17 +	mutex_lock(&xs_state.response_mutex);
    3.18  }
    3.19  
    3.20  void xs_resume(void)
    3.21 @@ -661,6 +665,7 @@ void xs_resume(void)
    3.22  	struct xenbus_watch *watch;
    3.23  	char token[sizeof(watch) * 2 + 1];
    3.24  
    3.25 +	mutex_unlock(&xs_state.response_mutex);
    3.26  	mutex_unlock(&xs_state.request_mutex);
    3.27  
    3.28  	/* No need for watches_lock: the suspend_mutex is sufficient. */
    3.29 @@ -674,6 +679,7 @@ void xs_resume(void)
    3.30  
    3.31  void xs_suspend_cancel(void)
    3.32  {
    3.33 +	mutex_unlock(&xs_state.response_mutex);
    3.34  	mutex_unlock(&xs_state.request_mutex);
    3.35  	up_write(&xs_state.suspend_mutex);
    3.36  }
    3.37 @@ -737,19 +743,27 @@ static int process_msg(void)
    3.38  	char *body;
    3.39  	int err;
    3.40  
    3.41 -	err = xb_wait_for_data_to_read();
    3.42 -	if (err)
    3.43 -	    return err;
    3.44 +	/*
    3.45 +	 * We must disallow save/restore while reading a xenstore message.
    3.46 +	 * A partial read across s/r leaves us out of sync with xenstored.
    3.47 +	 */
    3.48 +	for (;;) {
    3.49 +		err = xb_wait_for_data_to_read();
    3.50 +		if (err)
    3.51 +			return err;
    3.52 +		mutex_lock(&xs_state.response_mutex);
    3.53 +		if (xb_data_to_read())
    3.54 +			break;
    3.55 +		/* We raced with save/restore: pending data 'disappeared'. */
    3.56 +		mutex_unlock(&xs_state.response_mutex);
    3.57 +	}
    3.58 +
    3.59  
    3.60  	msg = kmalloc(sizeof(*msg), GFP_KERNEL);
    3.61 -	if (msg == NULL)
    3.62 -		return -ENOMEM;
    3.63 -
    3.64 -	/*
    3.65 -	 * We are now committed to reading an entire message. Partial reads
    3.66 -	 * across save/restore leave us out of sync with the xenstore daemon.
    3.67 -	 */
    3.68 -	down_read(&xs_state.suspend_mutex);
    3.69 +	if (msg == NULL) {
    3.70 +		err = -ENOMEM;
    3.71 +		goto out;
    3.72 +	}
    3.73  
    3.74  	err = xb_read(&msg->hdr, sizeof(msg->hdr));
    3.75  	if (err) {
    3.76 @@ -803,7 +817,7 @@ static int process_msg(void)
    3.77  	}
    3.78  
    3.79   out:
    3.80 -	up_read(&xs_state.suspend_mutex);
    3.81 +	mutex_unlock(&xs_state.response_mutex);
    3.82  	return err;
    3.83  }
    3.84  
    3.85 @@ -833,6 +847,7 @@ int xs_init(void)
    3.86  	init_waitqueue_head(&xs_state.reply_waitq);
    3.87  
    3.88  	mutex_init(&xs_state.request_mutex);
    3.89 +	mutex_init(&xs_state.response_mutex);
    3.90  	init_rwsem(&xs_state.suspend_mutex);
    3.91  
    3.92  	/* Initialize the shared memory rings to talk to xenstored */
     4.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Wed Feb 28 13:22:20 2007 +0000
     4.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Wed Feb 28 14:13:09 2007 +0000
     4.3 @@ -230,11 +230,7 @@ def restore(xd, fd, dominfo = None, paus
     4.4          if not is_hvm and handler.console_mfn is None:
     4.5              raise XendError('Could not read console MFN')        
     4.6  
     4.7 -        dominfo.waitForDevices() # Wait for backends to set up
     4.8 -        if not paused:
     4.9 -            dominfo.unpause()
    4.10 -
    4.11 -         # get qemu state and create a tmp file for dm restore
    4.12 +        # get qemu state and create a tmp file for dm restore
    4.13          if is_hvm:
    4.14              qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
    4.15                                          "invalid device model signature read")
    4.16 @@ -257,6 +253,10 @@ def restore(xd, fd, dominfo = None, paus
    4.17          
    4.18          dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
    4.19          
    4.20 +        dominfo.waitForDevices() # Wait for backends to set up
    4.21 +        if not paused:
    4.22 +            dominfo.unpause()
    4.23 +
    4.24          return dominfo
    4.25      except:
    4.26          dominfo.destroy()
     5.1 --- a/tools/xenstore/xenstored_domain.c	Wed Feb 28 13:22:20 2007 +0000
     5.2 +++ b/tools/xenstore/xenstored_domain.c	Wed Feb 28 14:13:09 2007 +0000
     5.3 @@ -298,6 +298,7 @@ void do_introduce(struct connection *con
     5.4  	unsigned int domid;
     5.5  	unsigned long mfn;
     5.6  	evtchn_port_t port;
     5.7 +	int rc;
     5.8  
     5.9  	if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
    5.10  		send_error(conn, EINVAL);
    5.11 @@ -341,18 +342,22 @@ void do_introduce(struct connection *con
    5.12  		talloc_steal(domain->conn, domain);
    5.13  
    5.14  		fire_watches(conn, "@introduceDomain", false);
    5.15 -	}
    5.16 -	else {
    5.17 -		int rc;
    5.18 -
    5.19 +	} else if (domain->mfn == mfn) {
    5.20  		/* Use XS_INTRODUCE for recreating the xenbus event-channel. */
    5.21  		if (domain->port)
    5.22  			xc_evtchn_unbind(xce_handle, domain->port);
    5.23  		rc = xc_evtchn_bind_interdomain(xce_handle, domid, port);
    5.24  		domain->port = (rc == -1) ? 0 : rc;
    5.25  		domain->remote_port = port;
    5.26 +	} else {
    5.27 +		send_error(conn, EINVAL);
    5.28 +		return;
    5.29  	}
    5.30  
    5.31 +	/* Rings must be quiesced. */
    5.32 +	domain->interface->req_cons = domain->interface->req_prod = 0;
    5.33 +	domain->interface->rsp_cons = domain->interface->rsp_prod = 0;
    5.34 +
    5.35  	send_ack(conn, XS_INTRODUCE);
    5.36  }
    5.37