diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-03 03:59:45 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-03 03:59:45 +0200 |
commit | c000131c711f68cb68712e6553ddce5fa6ad5c5c (patch) | |
tree | bfb29b294e7e01d74f7f9a4ef040d27b0b936ced | |
parent | Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kern... (diff) | |
parent | rcu: fix hotplug vs rcu race (diff) | |
download | linux-c000131c711f68cb68712e6553ddce5fa6ad5c5c.tar.xz linux-c000131c711f68cb68712e6553ddce5fa6ad5c5c.zip |
Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* '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
-rw-r--r-- | kernel/rcuclassic.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/kernel/rcuclassic.c b/kernel/rcuclassic.c index f4ffbd0f306f..a38895a5b8e2 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c @@ -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); |