Browse Source

sched: Fix set_cpu_active() in cpu_down()

Sachin found cpu hotplug test failures on powerpc, which made
the kernel hang on his POWER box.

The problem is that we fail to re-activate a cpu when a
hot-unplug fails. Fix this by moving the de-activation into
_cpu_down after doing the initial checks.

Remove the synchronize_sched() calls and rely on those implied
by rebuilding the sched domains using the new mask.

Reported-by: Sachin Sant <sachinp@in.ibm.com>
Signed-off-by: Xiaotian Feng <dfeng@redhat.com>
Tested-by: Sachin Sant <sachinp@in.ibm.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20091216170517.500272612@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Xiaotian Feng 15 years ago
parent
commit
9ee349ad6d
1 changed files with 3 additions and 21 deletions
  1. 3 21
      kernel/cpu.c

+ 3 - 21
kernel/cpu.c

@@ -209,6 +209,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	cpu_hotplug_begin();
 	cpu_hotplug_begin();
+	set_cpu_active(cpu, false);
 	err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod,
 	err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod,
 					hcpu, -1, &nr_calls);
 					hcpu, -1, &nr_calls);
 	if (err == NOTIFY_BAD) {
 	if (err == NOTIFY_BAD) {
@@ -280,18 +281,6 @@ int __ref cpu_down(unsigned int cpu)
 		goto out;
 		goto out;
 	}
 	}
 
 
-	set_cpu_active(cpu, false);
-
-	/*
-	 * Make sure the all cpus did the reschedule and are not
-	 * using stale version of the cpu_active_mask.
-	 * This is not strictly necessary becuase stop_machine()
-	 * that we run down the line already provides the required
-	 * synchronization. But it's really a side effect and we do not
-	 * want to depend on the innards of the stop_machine here.
-	 */
-	synchronize_sched();
-
 	err = _cpu_down(cpu, 0);
 	err = _cpu_down(cpu, 0);
 
 
 out:
 out:
@@ -382,19 +371,12 @@ int disable_nonboot_cpus(void)
 		return error;
 		return error;
 	cpu_maps_update_begin();
 	cpu_maps_update_begin();
 	first_cpu = cpumask_first(cpu_online_mask);
 	first_cpu = cpumask_first(cpu_online_mask);
-	/* We take down all of the non-boot CPUs in one shot to avoid races
+	/*
+	 * We take down all of the non-boot CPUs in one shot to avoid races
 	 * with the userspace trying to use the CPU hotplug at the same time
 	 * with the userspace trying to use the CPU hotplug at the same time
 	 */
 	 */
 	cpumask_clear(frozen_cpus);
 	cpumask_clear(frozen_cpus);
 
 
-	for_each_online_cpu(cpu) {
-		if (cpu == first_cpu)
-			continue;
-		set_cpu_active(cpu, false);
-	}
-
-	synchronize_sched();
-
 	printk("Disabling non-boot CPUs ...\n");
 	printk("Disabling non-boot CPUs ...\n");
 	for_each_online_cpu(cpu) {
 	for_each_online_cpu(cpu) {
 		if (cpu == first_cpu)
 		if (cpu == first_cpu)