# 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
|