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

[Xen-changelog] Make xm save/restore work for SMP guest domains.



# HG changeset patch
# User sos22@xxxxxxxxxxxxxxxxxxxx
# Node ID 6e6cedc1763db80ac68fefbe6062594416c75aa1
# Parent  69f00d6ab5dcdfb440482315715522ee85e86f84
Make xm save/restore work for SMP guest domains.

Signed-off-by: Steven Smith, sos22@xxxxxxxxx

diff -r 69f00d6ab5dc -r 6e6cedc1763d 
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c     Wed Aug 17 13:34:42 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c     Wed Aug 17 14:37:22 2005
@@ -16,6 +16,8 @@
 #include <asm-xen/queues.h>
 #include <asm-xen/xenbus.h>
 #include <asm-xen/ctrl_if.h>
+#include <linux/cpu.h>
+#include <linux/kthread.h>
 
 #define SHUTDOWN_INVALID  -1
 #define SHUTDOWN_POWEROFF  0
@@ -58,7 +60,12 @@
 /* Ignore multiple shutdown requests. */
 static int shutting_down = SHUTDOWN_INVALID;
 
-static void __do_suspend(void)
+#ifndef CONFIG_HOTPLUG_CPU
+#define cpu_down(x) (-EOPNOTSUPP)
+#define cpu_up(x) (-EOPNOTSUPP)
+#endif
+
+static int __do_suspend(void *ignore)
 {
     int i, j;
     suspend_record_t *suspend_record;
@@ -104,10 +111,49 @@
     extern unsigned long max_pfn;
     extern unsigned int *pfn_to_mfn_frame_list;
 
+    cpumask_t feasible_cpus;
+    int err = 0;
+
+    BUG_ON(smp_processor_id() != 0);
+    BUG_ON(in_interrupt());
+
+#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
+    if (num_online_cpus() > 1) {
+       printk(KERN_WARNING "Can't suspend SMP guests without 
CONFIG_HOTPLUG_CPU\n");
+       return -EOPNOTSUPP;
+    }
+#endif
+
     suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL);
     if ( suspend_record == NULL )
         goto out;
 
+    /* Take all of the other cpus offline.  We need to be careful not
+       to get preempted between the final test for num_online_cpus()
+       == 1 and disabling interrupts, since otherwise userspace could
+       bring another cpu online, and then we'd be stuffed.  At the
+       same time, cpu_down can reschedule, so we need to enable
+       preemption while doing that.  This kind of sucks, but should be
+       correct. */
+    /* (We don't need to worry about other cpus bringing stuff up,
+       since by the time num_online_cpus() == 1, there aren't any
+       other cpus) */
+    cpus_clear(feasible_cpus);
+    preempt_disable();
+    while (num_online_cpus() > 1) {
+       preempt_enable();
+       for_each_online_cpu(i) {
+           if (i == 0)
+               continue;
+           err = cpu_down(i);
+           if (err != 0) {
+               printk(KERN_CRIT "Failed to take all CPUs down: %d.\n", err);
+               goto out_reenable_cpus;
+           }
+           cpu_set(i, feasible_cpus);
+       }
+    }
+
     suspend_record->nr_pfns = max_pfn; /* final number of pfns */
 
     __cli();
@@ -141,7 +187,10 @@
     memcpy(&suspend_record->resume_info, &xen_start_info,
            sizeof(xen_start_info));
 
+    /* We'll stop somewhere inside this hypercall.  When it returns,
+       we'll start resuming after the restore. */
     HYPERVISOR_suspend(virt_to_machine(suspend_record) >> PAGE_SHIFT);
+
 
     shutting_down = SHUTDOWN_INVALID; 
 
@@ -182,11 +231,26 @@
 
     usbif_resume();
 
+    preempt_enable();
+
     __sti();
+
+ out_reenable_cpus:
+    while (!cpus_empty(feasible_cpus)) {
+       i = first_cpu(feasible_cpus);
+       j = cpu_up(i);
+       if (j != 0) {
+           printk(KERN_CRIT "Failed to bring cpu %d back up (%d).\n",
+                  i, j);
+           err = j;
+       }
+       cpu_clear(i, feasible_cpus);
+    }
 
  out:
     if ( suspend_record != NULL )
         free_page((unsigned long)suspend_record);
+    return err;
 }
 
 static int shutdown_process(void *__unused)
@@ -233,6 +297,18 @@
     return 0;
 }
 
+static struct task_struct *kthread_create_on_cpu(int (*f)(void *arg),
+                                                void *arg,
+                                                const char *name,
+                                                int cpu)
+{
+    struct task_struct *p;
+    p = kthread_create(f, arg, name);
+    kthread_bind(p, cpu);
+    wake_up_process(p);
+    return p;
+}
+
 static void __shutdown_handler(void *unused)
 {
     int err;
@@ -245,7 +321,7 @@
     }
     else
     {
-        __do_suspend();
+       kthread_create_on_cpu(__do_suspend, NULL, "suspender", 0);
     }
 }
 

_______________________________________________
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®.