WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] xen: Fix PV resume race against anoth

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] xen: Fix PV resume race against another back-to-back suspend request.
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 29 Feb 2008 06:00:10 -0800
Delivery-date: Fri, 29 Feb 2008 06:00:04 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1204280953 0
# Node ID 49ffe9ef67d420bde98e7ead29c9b9bfc5b026ba
# Parent  87721beab1b907e45f101ed4075a75adab828b59
xen: Fix PV resume race against another back-to-back suspend request.
Previously the next suspend request was being dropped on the floor.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 drivers/xen/core/machine_reboot.c |   25 +++++++----
 drivers/xen/core/reboot.c         |   82 +++++++++++++++++++++++++-------------
 2 files changed, 70 insertions(+), 37 deletions(-)

diff -r 87721beab1b9 -r 49ffe9ef67d4 drivers/xen/core/machine_reboot.c
--- a/drivers/xen/core/machine_reboot.c Thu Feb 28 16:41:41 2008 +0000
+++ b/drivers/xen/core/machine_reboot.c Fri Feb 29 10:29:13 2008 +0000
@@ -129,13 +129,18 @@ static void post_suspend(int suspend_can
 
 #endif
 
-static int take_machine_down(void *p_fast_suspend)
-{
-       int fast_suspend = *(int *)p_fast_suspend;
+struct suspend {
+       int fast_suspend;
+       void (*resume_notifier)(void);
+};
+
+static int take_machine_down(void *_suspend)
+{
+       struct suspend *suspend = _suspend;
        int suspend_cancelled, err;
        extern void time_resume(void);
 
-       if (fast_suspend) {
+       if (suspend->fast_suspend) {
                BUG_ON(!irqs_disabled());
        } else {
                BUG_ON(irqs_disabled());
@@ -168,6 +173,7 @@ static int take_machine_down(void *p_fas
         */
        suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
 
+       suspend->resume_notifier();
        post_suspend(suspend_cancelled);
        gnttab_resume();
        if (!suspend_cancelled) {
@@ -178,7 +184,7 @@ static int take_machine_down(void *p_fas
                 * We do it here just in case, but there's no need if we are
                 * in fast-suspend mode as that implies a new enough Xen.
                 */
-               if (!fast_suspend) {
+               if (!suspend->fast_suspend) {
                        struct mmuext_op op;
                        op.cmd = MMUEXT_NEW_USER_BASEPTR;
                        op.arg1.mfn = pfn_to_mfn(__pa(__user_pgd(
@@ -190,15 +196,16 @@ static int take_machine_down(void *p_fas
        }
        time_resume();
 
-       if (!fast_suspend)
+       if (!suspend->fast_suspend)
                local_irq_enable();
 
        return suspend_cancelled;
 }
 
-int __xen_suspend(int fast_suspend)
+int __xen_suspend(int fast_suspend, void (*resume_notifier)(void))
 {
        int err, suspend_cancelled;
+       struct suspend suspend = { fast_suspend, resume_notifier };
 
        BUG_ON(smp_processor_id() != 0);
        BUG_ON(in_interrupt());
@@ -217,11 +224,11 @@ int __xen_suspend(int fast_suspend)
 
        if (fast_suspend) {
                xenbus_suspend();
-               err = stop_machine_run(take_machine_down, &fast_suspend, 0);
+               err = stop_machine_run(take_machine_down, &suspend, 0);
                if (err < 0)
                        xenbus_suspend_cancel();
        } else {
-               err = take_machine_down(&fast_suspend);
+               err = take_machine_down(&suspend);
        }
 
        if (err < 0)
diff -r 87721beab1b9 -r 49ffe9ef67d4 drivers/xen/core/reboot.c
--- a/drivers/xen/core/reboot.c Thu Feb 28 16:41:41 2008 +0000
+++ b/drivers/xen/core/reboot.c Fri Feb 29 10:29:13 2008 +0000
@@ -20,11 +20,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 #define SHUTDOWN_INVALID  -1
 #define SHUTDOWN_POWEROFF  0
 #define SHUTDOWN_SUSPEND   2
-/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
- * report a crash, not be instructed to crash!
- * HALT is the same as POWEROFF, as far as we're concerned.  The tools use
- * the distinction when we return the reason code to them.
- */
+#define SHUTDOWN_RESUMING  3
 #define SHUTDOWN_HALT      4
 
 /* Ignore multiple shutdown requests. */
@@ -36,7 +32,7 @@ static void __shutdown_handler(void *unu
 static void __shutdown_handler(void *unused);
 static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
 
-int __xen_suspend(int fast_suspend);
+int __xen_suspend(int fast_suspend, void (*resume_notifier)(void));
 
 static int shutdown_process(void *__unused)
 {
@@ -65,23 +61,49 @@ static int shutdown_process(void *__unus
        return 0;
 }
 
+static void xen_resume_notifier(void)
+{
+       int old_state = xchg(&shutting_down, SHUTDOWN_RESUMING);
+       BUG_ON(old_state != SHUTDOWN_SUSPEND);
+}
+
 static int xen_suspend(void *__unused)
 {
-       int err;
+       int err, old_state;
 
        daemonize("suspend");
        err = set_cpus_allowed(current, cpumask_of_cpu(0));
        if (err) {
                printk(KERN_ERR "Xen suspend can't run on CPU0 (%d)\n", err);
-               goto out;
-       }
-
-       err = __xen_suspend(fast_suspend);
-       if (err)
-               printk(KERN_ERR "Xen suspend failed (%d)\n", err);
-
- out:
-       shutting_down = SHUTDOWN_INVALID;
+               goto fail;
+       }
+
+       do {
+               err = __xen_suspend(fast_suspend, xen_resume_notifier);
+               if (err) {
+                       printk(KERN_ERR "Xen suspend failed (%d)\n", err);
+                       goto fail;
+               }
+               old_state = cmpxchg(
+                       &shutting_down, SHUTDOWN_RESUMING, SHUTDOWN_INVALID);
+       } while (old_state == SHUTDOWN_SUSPEND);
+
+       switch (old_state) {
+       case SHUTDOWN_INVALID:
+       case SHUTDOWN_SUSPEND:
+               BUG();
+       case SHUTDOWN_RESUMING:
+               break;
+       default:
+               schedule_work(&shutdown_work);
+               break;
+       }
+
+       return 0;
+
+ fail:
+       old_state = xchg(&shutting_down, SHUTDOWN_INVALID);
+       BUG_ON(old_state != SHUTDOWN_SUSPEND);
        return 0;
 }
 
@@ -106,9 +128,10 @@ static void shutdown_handler(struct xenb
        extern void ctrl_alt_del(void);
        char *str;
        struct xenbus_transaction xbt;
-       int err;
-
-       if (shutting_down != SHUTDOWN_INVALID)
+       int err, old_state, new_state = SHUTDOWN_INVALID;
+
+       if ((shutting_down != SHUTDOWN_INVALID) &&
+           (shutting_down != SHUTDOWN_RESUMING))
                return;
 
  again:
@@ -132,20 +155,23 @@ static void shutdown_handler(struct xenb
        }
 
        if (strcmp(str, "poweroff") == 0)
-               shutting_down = SHUTDOWN_POWEROFF;
+               new_state = SHUTDOWN_POWEROFF;
        else if (strcmp(str, "reboot") == 0)
                ctrl_alt_del();
        else if (strcmp(str, "suspend") == 0)
-               shutting_down = SHUTDOWN_SUSPEND;
+               new_state = SHUTDOWN_SUSPEND;
        else if (strcmp(str, "halt") == 0)
-               shutting_down = SHUTDOWN_HALT;
-       else {
+               new_state = SHUTDOWN_HALT;
+       else
                printk("Ignoring shutdown request: %s\n", str);
-               shutting_down = SHUTDOWN_INVALID;
-       }
-
-       if (shutting_down != SHUTDOWN_INVALID)
-               schedule_work(&shutdown_work);
+
+       if (new_state != SHUTDOWN_INVALID) {
+               old_state = xchg(&shutting_down, new_state);
+               if (old_state == SHUTDOWN_INVALID)
+                       schedule_work(&shutdown_work);
+               else
+                       BUG_ON(old_state != SHUTDOWN_RESUMING);
+       }
 
        kfree(str);
 }

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] xen: Fix PV resume race against another back-to-back suspend request., Xen patchbot-linux-2.6.18-xen <=