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

[Xen-changelog] [xen-unstable] More PV save/restore fixes.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1172671989 0
# Node ID 1ec0d322402eaa5b85691f8b4df704fe39d14263
# Parent  0f0ac445bf82e4dca6d3b22d646e0bf278bd3757
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@xxxxxxxxxxxxx>
---
 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c |   23 ++++++++--
 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h |    1 
 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c    |   39 +++++++++++------
 tools/python/xen/xend/XendCheckpoint.py                |   10 ++--
 tools/xenstore/xenstored_domain.c                      |   15 ++++--
 5 files changed, 62 insertions(+), 26 deletions(-)

diff -r 0f0ac445bf82 -r 1ec0d322402e 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c    Wed Feb 28 
13:22:20 2007 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c    Wed Feb 28 
14:13:09 2007 +0000
@@ -137,12 +137,15 @@ int xb_write(const void *data, unsigned 
        return 0;
 }
 
+int xb_data_to_read(void)
+{
+       struct xenstore_domain_interface *intf = xen_store_interface;
+       return (intf->rsp_cons != intf->rsp_prod);
+}
+
 int xb_wait_for_data_to_read(void)
 {
-       struct xenstore_domain_interface *intf = xen_store_interface;
-       return wait_event_interruptible(
-               xb_waitq,
-               intf->rsp_cons != intf->rsp_prod);
+       return wait_event_interruptible(xb_waitq, xb_data_to_read());
 }
 
 int xb_read(void *data, unsigned len)
@@ -197,7 +200,19 @@ int xb_read(void *data, unsigned len)
 /* Set up interrupt handler off store event channel. */
 int xb_init_comms(void)
 {
+       struct xenstore_domain_interface *intf = xen_store_interface;
        int err;
+
+       if (intf->req_prod != intf->req_cons)
+               printk(KERN_ERR "XENBUS request ring is not quiescent "
+                      "(%08x:%08x)!\n", intf->req_cons, intf->req_prod);
+
+       if (intf->rsp_prod != intf->rsp_cons) {
+               printk(KERN_WARNING "XENBUS response ring is not quiescent "
+                      "(%08x:%08x): fixing up\n",
+                      intf->rsp_cons, intf->rsp_prod);
+               intf->rsp_cons = intf->rsp_prod;
+       }
 
        if (xenbus_irq)
                unbind_from_irqhandler(xenbus_irq, &xb_waitq);
diff -r 0f0ac445bf82 -r 1ec0d322402e 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h    Wed Feb 28 
13:22:20 2007 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h    Wed Feb 28 
14:13:09 2007 +0000
@@ -37,6 +37,7 @@ int xb_init_comms(void);
 /* Low level routines. */
 int xb_write(const void *data, unsigned len);
 int xb_read(void *data, unsigned len);
+int xb_data_to_read(void);
 int xb_wait_for_data_to_read(void);
 int xs_input_avail(void);
 extern struct xenstore_domain_interface *xen_store_interface;
diff -r 0f0ac445bf82 -r 1ec0d322402e 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c       Wed Feb 28 
13:22:20 2007 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c       Wed Feb 28 
14:13:09 2007 +0000
@@ -80,6 +80,9 @@ struct xs_handle {
        /* One request at a time. */
        struct mutex request_mutex;
 
+       /* Protect xenbus reader thread against save/restore. */
+       struct mutex response_mutex;
+
        /* Protect transactions against save/restore. */
        struct rw_semaphore suspend_mutex;
 };
@@ -654,6 +657,7 @@ void xs_suspend(void)
 {
        down_write(&xs_state.suspend_mutex);
        mutex_lock(&xs_state.request_mutex);
+       mutex_lock(&xs_state.response_mutex);
 }
 
 void xs_resume(void)
@@ -661,6 +665,7 @@ void xs_resume(void)
        struct xenbus_watch *watch;
        char token[sizeof(watch) * 2 + 1];
 
+       mutex_unlock(&xs_state.response_mutex);
        mutex_unlock(&xs_state.request_mutex);
 
        /* No need for watches_lock: the suspend_mutex is sufficient. */
@@ -674,6 +679,7 @@ void xs_resume(void)
 
 void xs_suspend_cancel(void)
 {
+       mutex_unlock(&xs_state.response_mutex);
        mutex_unlock(&xs_state.request_mutex);
        up_write(&xs_state.suspend_mutex);
 }
@@ -737,19 +743,27 @@ static int process_msg(void)
        char *body;
        int err;
 
-       err = xb_wait_for_data_to_read();
-       if (err)
-           return err;
+       /*
+        * We must disallow save/restore while reading a xenstore message.
+        * A partial read across s/r leaves us out of sync with xenstored.
+        */
+       for (;;) {
+               err = xb_wait_for_data_to_read();
+               if (err)
+                       return err;
+               mutex_lock(&xs_state.response_mutex);
+               if (xb_data_to_read())
+                       break;
+               /* We raced with save/restore: pending data 'disappeared'. */
+               mutex_unlock(&xs_state.response_mutex);
+       }
+
 
        msg = kmalloc(sizeof(*msg), GFP_KERNEL);
-       if (msg == NULL)
-               return -ENOMEM;
-
-       /*
-        * We are now committed to reading an entire message. Partial reads
-        * across save/restore leave us out of sync with the xenstore daemon.
-        */
-       down_read(&xs_state.suspend_mutex);
+       if (msg == NULL) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        err = xb_read(&msg->hdr, sizeof(msg->hdr));
        if (err) {
@@ -803,7 +817,7 @@ static int process_msg(void)
        }
 
  out:
-       up_read(&xs_state.suspend_mutex);
+       mutex_unlock(&xs_state.response_mutex);
        return err;
 }
 
@@ -833,6 +847,7 @@ int xs_init(void)
        init_waitqueue_head(&xs_state.reply_waitq);
 
        mutex_init(&xs_state.request_mutex);
+       mutex_init(&xs_state.response_mutex);
        init_rwsem(&xs_state.suspend_mutex);
 
        /* Initialize the shared memory rings to talk to xenstored */
diff -r 0f0ac445bf82 -r 1ec0d322402e tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Wed Feb 28 13:22:20 2007 +0000
+++ b/tools/python/xen/xend/XendCheckpoint.py   Wed Feb 28 14:13:09 2007 +0000
@@ -230,11 +230,7 @@ def restore(xd, fd, dominfo = None, paus
         if not is_hvm and handler.console_mfn is None:
             raise XendError('Could not read console MFN')        
 
-        dominfo.waitForDevices() # Wait for backends to set up
-        if not paused:
-            dominfo.unpause()
-
-         # get qemu state and create a tmp file for dm restore
+        # get qemu state and create a tmp file for dm restore
         if is_hvm:
             qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
                                         "invalid device model signature read")
@@ -257,6 +253,10 @@ def restore(xd, fd, dominfo = None, paus
         
         dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
         
+        dominfo.waitForDevices() # Wait for backends to set up
+        if not paused:
+            dominfo.unpause()
+
         return dominfo
     except:
         dominfo.destroy()
diff -r 0f0ac445bf82 -r 1ec0d322402e tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Wed Feb 28 13:22:20 2007 +0000
+++ b/tools/xenstore/xenstored_domain.c Wed Feb 28 14:13:09 2007 +0000
@@ -298,6 +298,7 @@ void do_introduce(struct connection *con
        unsigned int domid;
        unsigned long mfn;
        evtchn_port_t port;
+       int rc;
 
        if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
                send_error(conn, EINVAL);
@@ -341,17 +342,21 @@ void do_introduce(struct connection *con
                talloc_steal(domain->conn, domain);
 
                fire_watches(conn, "@introduceDomain", false);
-       }
-       else {
-               int rc;
-
+       } else if (domain->mfn == mfn) {
                /* Use XS_INTRODUCE for recreating the xenbus event-channel. */
                if (domain->port)
                        xc_evtchn_unbind(xce_handle, domain->port);
                rc = xc_evtchn_bind_interdomain(xce_handle, domid, port);
                domain->port = (rc == -1) ? 0 : rc;
                domain->remote_port = port;
-       }
+       } else {
+               send_error(conn, EINVAL);
+               return;
+       }
+
+       /* Rings must be quiesced. */
+       domain->interface->req_cons = domain->interface->req_prod = 0;
+       domain->interface->rsp_cons = domain->interface->rsp_prod = 0;
 
        send_ack(conn, XS_INTRODUCE);
 }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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