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

[Xen-devel] [PATCH] serialize suspend-resume process

To: Xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] serialize suspend-resume process
From: BVK Chaitanya <bayapuneni_chaitanya@xxxxxxxxxxxx>
Date: Thu, 31 Jul 2008 16:39:09 +0530
Cc:
Delivery-date: Thu, 31 Jul 2008 04:05:12 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mozilla-Thunderbird 2.0.0.14 (X11/20080509)
Hi,


With current suspend-resume code, there is no way for DOM-0 to identify that DOM-U resume is completed. It can potentially trigger suspend again before resume is completed.

Below patch makes suspend-resume process serialized.


regards,
--
bvk-chaitanya
suspend-resume process is serialized.

Under heavy load a suspend interrupt can create a new kthread and
start suspend process before old kthread's resuming completes.  This
patch serialzes suspend-resume using a counting semaphore and a
separate kthread.  Suspend interrupts up the semaphore and suspend
kthread downs the semaphore in a while(1) loop.

diff -r c2850a7f279d drivers/xen/core/reboot.c
--- a/drivers/xen/core/reboot.c Wed Jul 30 20:15:23 2008 +0530
+++ b/drivers/xen/core/reboot.c Thu Jul 31 21:35:46 2008 +0530
@@ -11,6 +11,7 @@
 #include <linux/kmod.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/kthread.h>
 
 #ifdef HAVE_XEN_PLATFORM_COMPAT_H
 #include <xen/platform-compat.h>
@@ -20,8 +21,6 @@ MODULE_LICENSE("Dual BSD/GPL");
 
 #define SHUTDOWN_INVALID  -1
 #define SHUTDOWN_POWEROFF  0
-#define SHUTDOWN_SUSPEND   2
-#define SHUTDOWN_RESUMING  3
 #define SHUTDOWN_HALT      4
 
 /* Ignore multiple shutdown requests. */
@@ -32,6 +31,11 @@ static int fast_suspend;
 
 static void __shutdown_handler(void *unused);
 static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
+
+static struct suspend_info {
+        struct semaphore nrequest; /* no. of suspend reqs */
+        atomic_t         resuming; /* is domain resuming ? */
+} suspend_info;
 
 int __xen_suspend(int fast_suspend, void (*resume_notifier)(void));
 
@@ -62,58 +66,11 @@ 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, 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 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;
-}
-
 static void __shutdown_handler(void *unused)
 {
        int err;
 
-       err = kernel_thread((shutting_down == SHUTDOWN_SUSPEND) ?
-                           xen_suspend : shutdown_process,
+       err = kernel_thread(shutdown_process,
                            NULL, CLONE_FS | CLONE_FILES);
 
        if (err < 0) {
@@ -131,8 +88,8 @@ static void shutdown_handler(struct xenb
        struct xenbus_transaction xbt;
        int err, old_state, new_state = SHUTDOWN_INVALID;
 
-       if ((shutting_down != SHUTDOWN_INVALID) &&
-           (shutting_down != SHUTDOWN_RESUMING))
+       if ((shutting_down != SHUTDOWN_INVALID) ||
+            atomic_read(&suspend_info.resuming))
                return;
 
  again:
@@ -155,12 +112,12 @@ static void shutdown_handler(struct xenb
                goto again;
        }
 
-       if (strcmp(str, "poweroff") == 0)
-               new_state = SHUTDOWN_POWEROFF;
+        if (strcmp(str, "suspend") == 0)
+                up(&suspend_info.nrequest); /* backward compatibility */
        else if (strcmp(str, "reboot") == 0)
                ctrl_alt_del();
-       else if (strcmp(str, "suspend") == 0)
-               new_state = SHUTDOWN_SUSPEND;
+       else if (strcmp(str, "poweroff") == 0)
+               new_state = SHUTDOWN_POWEROFF;
        else if (strcmp(str, "halt") == 0)
                new_state = SHUTDOWN_HALT;
        else
@@ -168,10 +125,8 @@ static void shutdown_handler(struct xenb
 
        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);
+                BUG_ON(old_state != SHUTDOWN_INVALID);
+                schedule_work(&shutdown_work);
        }
 
        kfree(str);
@@ -218,10 +173,41 @@ static struct xenbus_watch sysrq_watch =
        .callback = sysrq_handler
 };
 
+static void suspend_resume_notifier(void)
+{
+        atomic_set(&suspend_info.resuming, 1);
+        return;
+}
+
+static int suspend_machine(void *unused)
+{
+        int err = 0;
+        struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+
+        err = set_cpus_allowed(current, cpumask_of_cpu(0));
+        if (err) {
+                printk(KERN_ERR "Suspend thread couldn't switch to CPU0 
(%d)\n", err);
+                return err;
+        }
+
+        sched_setscheduler(current, SCHED_FIFO, &param);
+
+        while (1) {
+                /* decrement no. of suspend requests */
+                down(&suspend_info.nrequest);
+
+                err = __xen_suspend(fast_suspend, &suspend_resume_notifier);
+                if (err)
+                        printk(KERN_ERR "Domain suspend failed (%d)\n", err);
+
+                atomic_set(&suspend_info.resuming, 0);
+        }
+}
+
 static irqreturn_t suspend_int(int irq, void* dev_id, struct pt_regs *ptregs)
 {
-       shutting_down = SHUTDOWN_SUSPEND;
-       schedule_work(&shutdown_work);
+        /* increment no. of suspend requests */
+        up(&suspend_info.nrequest);
 
        return IRQ_HANDLED;
 }
@@ -251,6 +237,7 @@ static int setup_shutdown_watcher(void)
 static int setup_shutdown_watcher(void)
 {
        int err;
+        struct task_struct *t = NULL;
 
        xenbus_scanf(XBT_NIL, "control",
                     "platform-feature-multiprocessor-suspend",
@@ -267,6 +254,15 @@ static int setup_shutdown_watcher(void)
                printk(KERN_ERR "Failed to set sysrq watcher\n");
                return err;
        }
+
+        sema_init(&suspend_info.nrequest, 0);
+        atomic_set(&suspend_info.resuming, 0);
+        t = kthread_create(suspend_machine, &suspend_info, "ksuspend");
+        if (IS_ERR(t)) {
+                printk(KERN_ERR "Suspend thread creation failed\n");
+                return PTR_ERR(t);
+        }
+        wake_up_process(t);
 
        /* suspend event channel */
        err = setup_suspend_evtchn();
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel