[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] linux: More save/restore fixes. Fix deadlock of cpu_hotplug_lock vs
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1172685319 0 # Node ID c3c03089c59ef515766636dd4afef6573f3b6b42 # Parent 8ba425b640b3c7f81c17eb45972eff6eabe9f94d linux: More save/restore fixes. Fix deadlock of cpu_hotplug_lock vs workqueue_mutex. This is a new deadlock since the workqueue_mutex is acquired in the workqueue_cpu_calbback() function across CPU_UP_PREPARE->CPU_ONLINE. The fix is for us not to rudely grab the cpu_hotplug_lock() during save/restore -- it's really not necessary. This patch is applicable to any of our 2.6 kernels, but is absolutely required from 2.6.18 onwards. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c | 37 +++++------------ linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c | 24 +++++++---- linux-2.6-xen-sparse/drivers/xen/core/smpboot.c | 11 +---- linux-2.6-xen-sparse/include/xen/cpu_hotplug.h | 6 -- 4 files changed, 32 insertions(+), 46 deletions(-) diff -r 8ba425b640b3 -r c3c03089c59e linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c --- a/linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c Wed Feb 28 11:13:49 2007 -0500 +++ b/linux-2.6-xen-sparse/drivers/xen/core/cpu_hotplug.c Wed Feb 28 17:55:19 2007 +0000 @@ -121,29 +121,19 @@ arch_initcall(setup_vcpu_hotplug_event); int smp_suspend(void) { - int i, err; + int cpu, err; - lock_cpu_hotplug(); - - /* - * Take all other CPUs offline. We hold the hotplug mutex to - * avoid other processes bringing up CPUs under our feet. - */ - while (num_online_cpus() > 1) { - unlock_cpu_hotplug(); - for_each_online_cpu(i) { - if (i == 0) - continue; - err = cpu_down(i); - if (err) { - printk(KERN_CRIT "Failed to take all CPUs " - "down: %d.\n", err); - for_each_possible_cpu(i) - vcpu_hotplug(i); - return err; - } + for_each_online_cpu(cpu) { + if (cpu == 0) + continue; + err = cpu_down(cpu); + if (err) { + printk(KERN_CRIT "Failed to take all CPUs " + "down: %d.\n", err); + for_each_possible_cpu(cpu) + vcpu_hotplug(cpu); + return err; } - lock_cpu_hotplug(); } return 0; @@ -152,11 +142,6 @@ void smp_resume(void) void smp_resume(void) { int cpu; - - for_each_possible_cpu(cpu) - cpu_initialize_context(cpu); - - unlock_cpu_hotplug(); for_each_possible_cpu(cpu) vcpu_hotplug(cpu); diff -r 8ba425b640b3 -r c3c03089c59e linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Wed Feb 28 11:13:49 2007 -0500 +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Wed Feb 28 17:55:19 2007 +0000 @@ -97,6 +97,9 @@ static void post_suspend(int suspend_can pfn_to_mfn(xen_start_info->store_mfn); xen_start_info->console.domU.mfn = pfn_to_mfn(xen_start_info->console.domU.mfn); + } else { + extern cpumask_t cpu_initialized_map; + cpu_initialized_map = cpumask_of_cpu(0); } set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); @@ -147,13 +150,20 @@ int __xen_suspend(void) } #endif - err = smp_suspend(); - if (err) - return err; - - xenbus_suspend(); - - preempt_disable(); + for (;;) { + err = smp_suspend(); + if (err) + return err; + + xenbus_suspend(); + preempt_disable(); + + if (num_online_cpus() == 1) + break; + + preempt_enable(); + xenbus_suspend_cancel(); + } mm_pin_all(); local_irq_disable(); diff -r 8ba425b640b3 -r c3c03089c59e linux-2.6-xen-sparse/drivers/xen/core/smpboot.c --- a/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c Wed Feb 28 11:13:49 2007 -0500 +++ b/linux-2.6-xen-sparse/drivers/xen/core/smpboot.c Wed Feb 28 17:55:19 2007 +0000 @@ -47,7 +47,7 @@ EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_online_map); cpumask_t cpu_possible_map; EXPORT_SYMBOL(cpu_possible_map); -static cpumask_t cpu_initialized_map; +cpumask_t cpu_initialized_map; struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; EXPORT_SYMBOL(cpu_data); @@ -185,7 +185,7 @@ static void cpu_bringup_and_idle(void) cpu_idle(); } -void cpu_initialize_context(unsigned int cpu) +static void cpu_initialize_context(unsigned int cpu) { vcpu_guest_context_t ctxt; struct task_struct *idle = idle_task(cpu); @@ -195,7 +195,7 @@ void cpu_initialize_context(unsigned int struct Xgt_desc_struct *gdt_descr = &per_cpu(cpu_gdt_descr, cpu); #endif - if (cpu == 0) + if (cpu_test_and_set(cpu, cpu_initialized_map)) return; memset(&ctxt, 0, sizeof(ctxt)); @@ -417,10 +417,7 @@ int __devinit __cpu_up(unsigned int cpu) if (rc) return rc; - if (!cpu_isset(cpu, cpu_initialized_map)) { - cpu_set(cpu, cpu_initialized_map); - cpu_initialize_context(cpu); - } + cpu_initialize_context(cpu); if (num_online_cpus() == 1) alternatives_smp_switch(1); diff -r 8ba425b640b3 -r c3c03089c59e linux-2.6-xen-sparse/include/xen/cpu_hotplug.h --- a/linux-2.6-xen-sparse/include/xen/cpu_hotplug.h Wed Feb 28 11:13:49 2007 -0500 +++ b/linux-2.6-xen-sparse/include/xen/cpu_hotplug.h Wed Feb 28 17:55:19 2007 +0000 @@ -5,12 +5,6 @@ #include <linux/cpumask.h> #if defined(CONFIG_HOTPLUG_CPU) - -#if defined(CONFIG_X86) -void cpu_initialize_context(unsigned int cpu); -#else -#define cpu_initialize_context(cpu) ((void)0) -#endif int cpu_up_check(unsigned int cpu); void init_xenbus_allowed_cpumask(void); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |