Commit-ID: 94b5f312cfb4a66055d9b688dc9ab6b297eb9dcc Gitweb: https://git.kernel.org/tip/94b5f312cfb4a66055d9b688dc9ab6b297eb9dcc Author: Jakub Kicinski <[email protected]> AuthorDate: Fri, 29 Mar 2019 17:08:54 -0700 Committer: Ingo Molnar <[email protected]> CommitDate: Mon, 29 Apr 2019 08:29:21 +0200
locking/static_key: Don't take sleeping locks in __static_key_slow_dec_deferred() Changing jump_label state is protected by jump_label_lock(). Rate limited static_key_slow_dec(), however, will never directly call jump_label_update(), it will schedule a delayed work instead. Therefore it's unnecessary to take both the cpus_read_lock() and jump_label_lock(). This allows static_key_slow_dec_deferred() to be called from atomic contexts, like socket destructing in net/tls, without the need for another indirection. Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Simon Horman <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Paul E. McKenney <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Will Deacon <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]> --- kernel/jump_label.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/kernel/jump_label.c b/kernel/jump_label.c index 02c3d11264dd..de6efdecc70d 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -221,9 +221,7 @@ static bool static_key_slow_try_dec(struct static_key *key) return true; } -static void __static_key_slow_dec_cpuslocked(struct static_key *key, - unsigned long rate_limit, - struct delayed_work *work) +static void __static_key_slow_dec_cpuslocked(struct static_key *key) { lockdep_assert_cpus_held(); @@ -231,23 +229,15 @@ static void __static_key_slow_dec_cpuslocked(struct static_key *key, return; jump_label_lock(); - if (atomic_dec_and_test(&key->enabled)) { - if (rate_limit) { - atomic_inc(&key->enabled); - schedule_delayed_work(work, rate_limit); - } else { - jump_label_update(key); - } - } + if (atomic_dec_and_test(&key->enabled)) + jump_label_update(key); jump_label_unlock(); } -static void __static_key_slow_dec(struct static_key *key, - unsigned long rate_limit, - struct delayed_work *work) +static void __static_key_slow_dec(struct static_key *key) { cpus_read_lock(); - __static_key_slow_dec_cpuslocked(key, rate_limit, work); + __static_key_slow_dec_cpuslocked(key); cpus_read_unlock(); } @@ -255,21 +245,21 @@ void jump_label_update_timeout(struct work_struct *work) { struct static_key_deferred *key = container_of(work, struct static_key_deferred, work.work); - __static_key_slow_dec(&key->key, 0, NULL); + __static_key_slow_dec(&key->key); } EXPORT_SYMBOL_GPL(jump_label_update_timeout); void static_key_slow_dec(struct static_key *key) { STATIC_KEY_CHECK_USE(key); - __static_key_slow_dec(key, 0, NULL); + __static_key_slow_dec(key); } EXPORT_SYMBOL_GPL(static_key_slow_dec); void static_key_slow_dec_cpuslocked(struct static_key *key) { STATIC_KEY_CHECK_USE(key); - __static_key_slow_dec_cpuslocked(key, 0, NULL); + __static_key_slow_dec_cpuslocked(key); } void __static_key_slow_dec_deferred(struct static_key *key, @@ -277,7 +267,11 @@ void __static_key_slow_dec_deferred(struct static_key *key, unsigned long timeout) { STATIC_KEY_CHECK_USE(key); - __static_key_slow_dec(key, timeout, work); + + if (static_key_slow_try_dec(key)) + return; + + schedule_delayed_work(work, timeout); } EXPORT_SYMBOL_GPL(__static_key_slow_dec_deferred);

