lockdep_unregister_key() waits for is_dynamic_key() callers with synchronize_rcu_expedited(), which requires system-wide coordination. Make is_dynamic_key() protect the hash bucket with a hazard pointer and use hazptr_synchronize() to wait for traversals of that bucket.
The hash bucket returned by keyhashentry() has a stable address, so it can be used as the hazptr synchronization target. Keep the key hashlist lifetime RCU-based with hlist_del_rcu() and call_rcu(). Protect the traversal with the hazptr scoped_guard() added earlier in this series. This adapts the lockdep use case from Boqun Feng's shazptr series to the current hazptr API. Link: https://lore.kernel.org/lkml/[email protected]/ Signed-off-by: Kunwu Chan <[email protected]> --- kernel/locking/lockdep.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index c56a7f91d72e..d1ce5ace7fbf 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -58,6 +58,7 @@ #include <linux/context_tracking.h> #include <linux/console.h> #include <linux/kasan.h> +#include <linux/hazptr.h> #include <asm/sections.h> @@ -1280,14 +1281,19 @@ static bool is_dynamic_key(const struct lock_class_key *key) hash_head = keyhashentry(key); - rcu_read_lock(); - hlist_for_each_entry_rcu(k, hash_head, hash_entry) { - if (k == key) { - found = true; - break; + { + struct hazptr_ctx ctx; + void *bucket = hash_head; + + scoped_guard(hazptr, &ctx, &bucket) { + hlist_for_each_entry_rcu(k, hash_head, hash_entry, 1) { + if (k == key) { + found = true; + break; + } + } } } - rcu_read_unlock(); return found; } @@ -6683,11 +6689,10 @@ void lockdep_unregister_key(struct lock_class_key *key) * * Some operations like __qdisc_destroy() will call this in a debug * kernel, and the network traffic is disabled while waiting, hence - * the delay of the wait matters in debugging cases. Currently use a - * synchronize_rcu_expedited() to speed up the wait at the cost of - * system IPIs. TODO: Replace RCU with hazptr for this. + * the delay of the wait matters in debugging cases. Replace the + * expedited RCU wait with hazptr_synchronize(). */ - synchronize_rcu_expedited(); + hazptr_synchronize(keyhashentry(key)); } EXPORT_SYMBOL_GPL(lockdep_unregister_key); -- 2.43.0

