Commit e5d981df9a1d3f13dfff083ab0578daedbcd9e8a
Committed by
Greg Kroah-Hartman
1 parent
72e5a2bdf7
Exists in
smarc_8mm_imx_4.14.98_2.0.0_ga
and in
4 other branches
sched/core: Fix cpu.max vs. cpuhotplug deadlock
commit ce48c146495a1a50e48cdbfbfaba3e708be7c07c upstream Tejun reported the following cpu-hotplug lock (percpu-rwsem) read recursion: tg_set_cfs_bandwidth() get_online_cpus() cpus_read_lock() cfs_bandwidth_usage_inc() static_key_slow_inc() cpus_read_lock() Reported-by: Tejun Heo <tj@kernel.org> Tested-by: Tejun Heo <tj@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20180122215328.GP3397@worktop Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 3 changed files with 18 additions and 5 deletions Side-by-side Diff
include/linux/jump_label.h
... | ... | @@ -160,6 +160,8 @@ |
160 | 160 | extern int jump_label_text_reserved(void *start, void *end); |
161 | 161 | extern void static_key_slow_inc(struct static_key *key); |
162 | 162 | extern void static_key_slow_dec(struct static_key *key); |
163 | +extern void static_key_slow_inc_cpuslocked(struct static_key *key); | |
164 | +extern void static_key_slow_dec_cpuslocked(struct static_key *key); | |
163 | 165 | extern void jump_label_apply_nops(struct module *mod); |
164 | 166 | extern int static_key_count(struct static_key *key); |
165 | 167 | extern void static_key_enable(struct static_key *key); |
... | ... | @@ -222,6 +224,9 @@ |
222 | 224 | atomic_dec(&key->enabled); |
223 | 225 | } |
224 | 226 | |
227 | +#define static_key_slow_inc_cpuslocked(key) static_key_slow_inc(key) | |
228 | +#define static_key_slow_dec_cpuslocked(key) static_key_slow_dec(key) | |
229 | + | |
225 | 230 | static inline int jump_label_text_reserved(void *start, void *end) |
226 | 231 | { |
227 | 232 | return 0; |
... | ... | @@ -416,6 +421,8 @@ |
416 | 421 | |
417 | 422 | #define static_branch_inc(x) static_key_slow_inc(&(x)->key) |
418 | 423 | #define static_branch_dec(x) static_key_slow_dec(&(x)->key) |
424 | +#define static_branch_inc_cpuslocked(x) static_key_slow_inc_cpuslocked(&(x)->key) | |
425 | +#define static_branch_dec_cpuslocked(x) static_key_slow_dec_cpuslocked(&(x)->key) | |
419 | 426 | |
420 | 427 | /* |
421 | 428 | * Normal usage; boolean enable/disable. |
kernel/jump_label.c
... | ... | @@ -79,7 +79,7 @@ |
79 | 79 | } |
80 | 80 | EXPORT_SYMBOL_GPL(static_key_count); |
81 | 81 | |
82 | -static void static_key_slow_inc_cpuslocked(struct static_key *key) | |
82 | +void static_key_slow_inc_cpuslocked(struct static_key *key) | |
83 | 83 | { |
84 | 84 | int v, v1; |
85 | 85 | |
... | ... | @@ -180,7 +180,7 @@ |
180 | 180 | } |
181 | 181 | EXPORT_SYMBOL_GPL(static_key_disable); |
182 | 182 | |
183 | -static void static_key_slow_dec_cpuslocked(struct static_key *key, | |
183 | +static void __static_key_slow_dec_cpuslocked(struct static_key *key, | |
184 | 184 | unsigned long rate_limit, |
185 | 185 | struct delayed_work *work) |
186 | 186 | { |
... | ... | @@ -211,7 +211,7 @@ |
211 | 211 | struct delayed_work *work) |
212 | 212 | { |
213 | 213 | cpus_read_lock(); |
214 | - static_key_slow_dec_cpuslocked(key, rate_limit, work); | |
214 | + __static_key_slow_dec_cpuslocked(key, rate_limit, work); | |
215 | 215 | cpus_read_unlock(); |
216 | 216 | } |
217 | 217 | |
... | ... | @@ -228,6 +228,12 @@ |
228 | 228 | __static_key_slow_dec(key, 0, NULL); |
229 | 229 | } |
230 | 230 | EXPORT_SYMBOL_GPL(static_key_slow_dec); |
231 | + | |
232 | +void static_key_slow_dec_cpuslocked(struct static_key *key) | |
233 | +{ | |
234 | + STATIC_KEY_CHECK_USE(); | |
235 | + __static_key_slow_dec_cpuslocked(key, 0, NULL); | |
236 | +} | |
231 | 237 | |
232 | 238 | void static_key_slow_dec_deferred(struct static_key_deferred *key) |
233 | 239 | { |
kernel/sched/fair.c
... | ... | @@ -4040,12 +4040,12 @@ |
4040 | 4040 | |
4041 | 4041 | void cfs_bandwidth_usage_inc(void) |
4042 | 4042 | { |
4043 | - static_key_slow_inc(&__cfs_bandwidth_used); | |
4043 | + static_key_slow_inc_cpuslocked(&__cfs_bandwidth_used); | |
4044 | 4044 | } |
4045 | 4045 | |
4046 | 4046 | void cfs_bandwidth_usage_dec(void) |
4047 | 4047 | { |
4048 | - static_key_slow_dec(&__cfs_bandwidth_used); | |
4048 | + static_key_slow_dec_cpuslocked(&__cfs_bandwidth_used); | |
4049 | 4049 | } |
4050 | 4050 | #else /* HAVE_JUMP_LABEL */ |
4051 | 4051 | static bool cfs_bandwidth_used(void) |