diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-02 21:59:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-02 21:59:45 -0400 |
commit | c000131c711f68cb68712e6553ddce5fa6ad5c5c (patch) | |
tree | bfb29b294e7e01d74f7f9a4ef040d27b0b936ced /kernel | |
parent | 041924ec2f40efa6a3163144a5481a000804199d (diff) | |
parent | 8558f8f81680a43d383abd1b5f23d3501fedfa65 (diff) |
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
Diffstat (limited to 'kernel')
-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 f4ffbd0f306..a38895a5b8e 100644 --- a/kernel/rcuclassic.c +++ b/kernel/rcuclassic.c | |||
@@ -89,8 +89,22 @@ static void force_quiescent_state(struct rcu_data *rdp, | |||
89 | /* | 89 | /* |
90 | * Don't send IPI to itself. With irqs disabled, | 90 | * Don't send IPI to itself. With irqs disabled, |
91 | * rdp->cpu is the current cpu. | 91 | * rdp->cpu is the current cpu. |
92 | * | ||
93 | * cpu_online_map is updated by the _cpu_down() | ||
94 | * using stop_machine_run(). Since we're in irqs disabled | ||
95 | * section, stop_machine_run() is not exectuting, hence | ||
96 | * the cpu_online_map is stable. | ||
97 | * | ||
98 | * However, a cpu might have been offlined _just_ before | ||
99 | * we disabled irqs while entering here. | ||
100 | * And rcu subsystem might not yet have handled the CPU_DEAD | ||
101 | * notification, leading to the offlined cpu's bit | ||
102 | * being set in the rcp->cpumask. | ||
103 | * | ||
104 | * Hence cpumask = (rcp->cpumask & cpu_online_map) to prevent | ||
105 | * sending smp_reschedule() to an offlined CPU. | ||
92 | */ | 106 | */ |
93 | cpumask = rcp->cpumask; | 107 | cpus_and(cpumask, rcp->cpumask, cpu_online_map); |
94 | cpu_clear(rdp->cpu, cpumask); | 108 | cpu_clear(rdp->cpu, cpumask); |
95 | for_each_cpu_mask(cpu, cpumask) | 109 | for_each_cpu_mask(cpu, cpumask) |
96 | smp_send_reschedule(cpu); | 110 | smp_send_reschedule(cpu); |