Make xen_suspend handle resume.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 19 Jan 2007 16:06:09 +0000 (16:06 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 19 Jan 2007 16:06:09 +0000 (16:06 +0000)
Don't destroy xenstore watches on suspend, and only recreate them when
resuming in a new domain. Likewise, only invoke frontend device resume
code when in a new domain (the resume functions all tear down the
existing function and wait for the backend to negotiate a new one,
which does not happen in the source domain).

Signed-off-by: Brendan Cully <brendan@cs.ubc.ca>
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
linux-2.6-xen-sparse/include/xen/xenbus.h

index 02ee7f4728bb055db733a8d3eb6fb61df7c11549..b69efd61f97fd6d536da0a07787ea839079c8429 100644 (file)
@@ -85,13 +85,20 @@ static void pre_suspend(void)
                mfn_to_pfn(xen_start_info->console.domU.mfn);
 }
 
-static void post_suspend(void)
+static void post_suspend(int suspend_cancelled)
 {
        int i, j, k, fpp;
        extern unsigned long max_pfn;
        extern unsigned long *pfn_to_mfn_frame_list_list;
        extern unsigned long *pfn_to_mfn_frame_list[];
 
+       if (suspend_cancelled) {
+               xen_start_info->store_mfn =
+                       pfn_to_mfn(xen_start_info->store_mfn);
+               xen_start_info->console.domU.mfn =
+                       pfn_to_mfn(xen_start_info->console.domU.mfn);
+       }
+       
        set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info);
 
        HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
@@ -120,13 +127,13 @@ static void post_suspend(void)
 #define switch_idle_mm()       ((void)0)
 #define mm_pin_all()           ((void)0)
 #define pre_suspend()          ((void)0)
-#define post_suspend()         ((void)0)
+#define post_suspend(x)                ((void)0)
 
 #endif
 
 int __xen_suspend(void)
 {
-       int err;
+       int err, suspend_cancelled;
 
        extern void time_resume(void);
 
@@ -158,16 +165,17 @@ int __xen_suspend(void)
        pre_suspend();
 
        /*
-        * We'll stop somewhere inside this hypercall. When it returns,
-        * we'll start resuming after the restore.
+        * This hypercall returns 1 if suspend was cancelled or the domain was
+        * merely checkpointed, and 0 if it is resuming in a new domain.
         */
-       HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
+       suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
 
-       post_suspend();
+       post_suspend(suspend_cancelled);
 
        gnttab_resume();
 
-       irq_resume();
+       if (!suspend_cancelled)
+               irq_resume();
 
        time_resume();
 
@@ -175,9 +183,12 @@ int __xen_suspend(void)
 
        local_irq_enable();
 
-       xencons_resume();
-
-       xenbus_resume();
+       if (!suspend_cancelled) {
+               xencons_resume();
+               xenbus_resume();
+       } else {
+               xenbus_suspend_cancel();
+       }
 
        smp_resume();
 
index eee22afbb8a2e3189f679aeb24f2822f85a24c16..e099114abcbbcefa918c39f2628c629dfe64caaa 100644 (file)
@@ -736,6 +736,11 @@ void xenbus_resume(void)
 }
 EXPORT_SYMBOL_GPL(xenbus_resume);
 
+void xenbus_suspend_cancel(void)
+{
+       xs_suspend_cancel();
+}
+EXPORT_SYMBOL_GPL(xenbus_suspend_cancel);
 
 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
 int xenstored_ready = 0;
index 4c5052d13a2ba01790fcf66856fe91b0487bb321..23b99b86f5a0fa54d6fbe7358a276c31c91c5d67 100644 (file)
@@ -668,17 +668,7 @@ EXPORT_SYMBOL_GPL(unregister_xenbus_watch);
 
 void xs_suspend(void)
 {
-       struct xenbus_watch *watch;
-       char token[sizeof(watch) * 2 + 1];
-
        down_write(&xs_state.suspend_mutex);
-
-       /* No need for watches_lock: the suspend_mutex is sufficient. */
-       list_for_each_entry(watch, &watches, list) {
-               sprintf(token, "%lX", (long)watch);
-               xs_unwatch(watch->node, token);
-       }
-
        mutex_lock(&xs_state.request_mutex);
 }
 
@@ -698,6 +688,12 @@ void xs_resume(void)
        up_write(&xs_state.suspend_mutex);
 }
 
+void xs_suspend_cancel(void)
+{
+       mutex_unlock(&xs_state.request_mutex);
+       up_write(&xs_state.suspend_mutex);
+}
+
 static int xenwatch_handle_callback(void *data)
 {
        struct xs_stored_msg *msg = data;
index 3f525fa2dd7c646199aa099c131ba23a507b7a93..72eb9224acca65cde21844a2c38b895ecfbe4f81 100644 (file)
@@ -160,13 +160,15 @@ int register_xenbus_watch(struct xenbus_watch *watch);
 void unregister_xenbus_watch(struct xenbus_watch *watch);
 void xs_suspend(void);
 void xs_resume(void);
+void xs_suspend_cancel(void);
 
 /* Used by xenbus_dev to borrow kernel's store connection. */
 void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
 
-/* Called from xen core code. */
+/* Prepare for domain suspend: then resume or cancel the suspend. */
 void xenbus_suspend(void);
 void xenbus_resume(void);
+void xenbus_suspend_cancel(void);
 
 #define XENBUS_IS_ERR_READ(str) ({                     \
        if (!IS_ERR(str) && strlen(str) == 0) {         \