diff --git a/kernel/cpu.c b/kernel/cpu.c index d96656f87ab257..f925bd6a461f20 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -1281,6 +1281,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen, bool hasdied = false; int mycpu; cpumask_var_t cpumask; + cpumask_var_t cpumask_org; if (num_online_cpus() == 1) return -EBUSY; @@ -1291,6 +1292,12 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen, /* Move the downtaker off the unplug cpu */ if (!alloc_cpumask_var(&cpumask, GFP_KERNEL)) return -ENOMEM; + if (!alloc_cpumask_var(&cpumask_org, GFP_KERNEL)) { + free_cpumask_var(cpumask); + return -ENOMEM; + } + + cpumask_copy(cpumask_org, tsk_cpus_allowed(current)); cpumask_andnot(cpumask, cpu_online_mask, cpumask_of(cpu)); set_cpus_allowed_ptr(current, cpumask); free_cpumask_var(cpumask); @@ -1299,7 +1306,8 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen, if (mycpu == cpu) { printk(KERN_ERR "Yuck! Still on unplug CPU\n!"); migrate_enable(); - return -EBUSY; + ret = -EBUSY; + goto restore_cpus; } cpu_hotplug_begin(); @@ -1353,6 +1361,9 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen, /* This post dead nonsense must die */ if (!ret && hasdied) cpu_notify_nofail(CPU_POST_DEAD, cpu); +restore_cpus: + set_cpus_allowed_ptr(current, cpumask_org); + free_cpumask_var(cpumask_org); return ret; }