diff options
author | Richard Cochran <rcochran@linutronix.de> | 2016-07-27 05:08:18 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-07-28 12:56:22 -0400 |
commit | 4fae16dffb812f0e0d98a0b2b0856ca48ca63e6c (patch) | |
tree | c661ae0eaa75eb0f4af66870bb0c34a5b1c4c273 | |
parent | cd894f149732a06ba4b2ccdc4cb86edf7ff68620 (diff) |
timers/core: Correct callback order during CPU hot plug
On the tear-down path, the dead CPU callback for the timers was
misplaced within the 'cpuhp_state' enumeration. There is a hidden
dependency between the timers and block multiqueue. The timers
callback must happen before the block multiqueue callback otherwise a
RCU stall occurs.
Move the timers callback to the proper place in the state machine.
Reported-and-tested-by: Jon Hunter <jonathanh@nvidia.com>
Reported-by: kbuild test robot <lkp@intel.com>
Fixes: 24f73b99716a ("timers/core: Convert to hotplug state machine")
Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: John Stultz <john.stultz@linaro.org>
Cc: rt@linutronix.de
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/1469610498-25914-1-git-send-email-rcochran@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | include/linux/cpuhotplug.h | 2 | ||||
-rw-r--r-- | kernel/cpu.c | 15 |
2 files changed, 11 insertions, 6 deletions
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 6d405db6fb12..242bf530edfc 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h | |||
@@ -20,9 +20,9 @@ enum cpuhp_state { | |||
20 | CPUHP_PROFILE_PREPARE, | 20 | CPUHP_PROFILE_PREPARE, |
21 | CPUHP_X2APIC_PREPARE, | 21 | CPUHP_X2APIC_PREPARE, |
22 | CPUHP_SMPCFD_PREPARE, | 22 | CPUHP_SMPCFD_PREPARE, |
23 | CPUHP_TIMERS_DEAD, | ||
24 | CPUHP_RCUTREE_PREP, | 23 | CPUHP_RCUTREE_PREP, |
25 | CPUHP_NOTIFY_PREPARE, | 24 | CPUHP_NOTIFY_PREPARE, |
25 | CPUHP_TIMERS_DEAD, | ||
26 | CPUHP_BRINGUP_CPU, | 26 | CPUHP_BRINGUP_CPU, |
27 | CPUHP_AP_IDLE_DEAD, | 27 | CPUHP_AP_IDLE_DEAD, |
28 | CPUHP_AP_OFFLINE, | 28 | CPUHP_AP_OFFLINE, |
diff --git a/kernel/cpu.c b/kernel/cpu.c index f24f45915b54..341bf80f80bd 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -1200,11 +1200,6 @@ static struct cpuhp_step cpuhp_bp_states[] = { | |||
1200 | .startup = smpcfd_prepare_cpu, | 1200 | .startup = smpcfd_prepare_cpu, |
1201 | .teardown = smpcfd_dead_cpu, | 1201 | .teardown = smpcfd_dead_cpu, |
1202 | }, | 1202 | }, |
1203 | [CPUHP_TIMERS_DEAD] = { | ||
1204 | .name = "timers dead", | ||
1205 | .startup = NULL, | ||
1206 | .teardown = timers_dead_cpu, | ||
1207 | }, | ||
1208 | [CPUHP_RCUTREE_PREP] = { | 1203 | [CPUHP_RCUTREE_PREP] = { |
1209 | .name = "RCU-tree prepare", | 1204 | .name = "RCU-tree prepare", |
1210 | .startup = rcutree_prepare_cpu, | 1205 | .startup = rcutree_prepare_cpu, |
@@ -1221,6 +1216,16 @@ static struct cpuhp_step cpuhp_bp_states[] = { | |||
1221 | .skip_onerr = true, | 1216 | .skip_onerr = true, |
1222 | .cant_stop = true, | 1217 | .cant_stop = true, |
1223 | }, | 1218 | }, |
1219 | /* | ||
1220 | * On the tear-down path, timers_dead_cpu() must be invoked | ||
1221 | * before blk_mq_queue_reinit_notify() from notify_dead(), | ||
1222 | * otherwise a RCU stall occurs. | ||
1223 | */ | ||
1224 | [CPUHP_TIMERS_DEAD] = { | ||
1225 | .name = "timers dead", | ||
1226 | .startup = NULL, | ||
1227 | .teardown = timers_dead_cpu, | ||
1228 | }, | ||
1224 | /* Kicks the plugged cpu into life */ | 1229 | /* Kicks the plugged cpu into life */ |
1225 | [CPUHP_BRINGUP_CPU] = { | 1230 | [CPUHP_BRINGUP_CPU] = { |
1226 | .name = "cpu:bringup", | 1231 | .name = "cpu:bringup", |