Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Jul 2008 01:59:45 +0000 (18:59 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Jul 2008 01:59:45 +0000 (18:59 -0700)
* 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  rcu: fix hotplug vs rcu race

kernel/rcuclassic.c

index f4ffbd0..a38895a 100644 (file)
@@ -89,8 +89,22 @@ static void force_quiescent_state(struct rcu_data *rdp,
                /*
                 * Don't send IPI to itself. With irqs disabled,
                 * rdp->cpu is the current cpu.
+                *
+                * cpu_online_map is updated by the _cpu_down()
+                * using stop_machine_run(). Since we're in irqs disabled
+                * section, stop_machine_run() is not exectuting, hence
+                * the cpu_online_map is stable.
+                *
+                * However,  a cpu might have been offlined _just_ before
+                * we disabled irqs while entering here.
+                * And rcu subsystem might not yet have handled the CPU_DEAD
+                * notification, leading to the offlined cpu's bit
+                * being set in the rcp->cpumask.
+                *
+                * Hence cpumask = (rcp->cpumask & cpu_online_map) to prevent
+                * sending smp_reschedule() to an offlined CPU.
                 */
-               cpumask = rcp->cpumask;
+               cpus_and(cpumask, rcp->cpumask, cpu_online_map);
                cpu_clear(rdp->cpu, cpumask);
                for_each_cpu_mask(cpu, cpumask)
                        smp_send_reschedule(cpu);