Linux cryptographic layer development
 help / color / mirror / Atom feed
* [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks
@ 2026-08-01 10:13 quanyeyang via B4 Relay
  2026-08-01 11:12 ` NeilBrown
  2026-08-14 19:27 ` kernel test robot
  0 siblings, 2 replies; 6+ messages in thread
From: quanyeyang via B4 Relay @ 2026-08-01 10:13 UTC (permalink / raw)
  To: Thomas Graf, Herbert Xu, Andrew Morton, NeilBrown,
	David S. Miller
  Cc: linux-crypto, linux-kernel, syzbot+ef8d17bae14efb960935,
	quanyeyang

From: quanyeyang <quanyemostima@gmail.com>

All bucket tables currently share a single lockdep class. This makes
lockdep conflate bucket locks from unrelated rhashtable instances.

A BPF program attached to lock_release can expose this when pidfs
inserts a pid. The tracepoint runs before lockdep removes the pidfs
bucket lock from the task's held-lock stack. Deleting an element from
a BPF RHASH map then acquires a bucket lock belonging to a different
rhashtable. Since both tables use the same class, lockdep reports
possible recursive locking.

Declare a separate bucket lock class key at each rhashtable_init() and
rhltable_init() call site, alongside the mutex class key. Store the
bucket key in struct rhashtable so tables created during resize keep
using the same class.

A targeted reproducer triggers the warning reliably before this change.
After the change, the nested BPF RHASH deletion still executes, but
lockdep no longer reports recursive locking.

Fixes: 149212f07856 ("rhashtable: add lockdep tracking to bucket bit-spin-locks.")
Reported-by: syzbot+ef8d17bae14efb960935@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=ef8d17bae14efb960935
Assisted-by: Cursor:GPT-5.6 Sol
Signed-off-by: quanyeyang <quanyemostima@gmail.com>
---
 include/linux/rhashtable-types.h | 20 ++++++++++++++------
 lib/rhashtable.c                 | 19 +++++++++++++------
 2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 57c11ec9dc64..4dea91a49ec8 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -82,6 +82,7 @@ struct rhashtable_params {
  * @mutex: Mutex to protect current/future table swapping
  * @lock: Spin lock to protect walker list
  * @nelems: Number of elements in table
+ * @bucket_lock_key: Per-init-site lockdep class for bucket bit-locks
  */
 struct rhashtable {
 	struct bucket_table __rcu	*tbl;
@@ -94,6 +95,7 @@ struct rhashtable {
 	struct mutex                    mutex;
 	spinlock_t			lock;
 	atomic_t			nelems;
+	struct lock_class_key		*bucket_lock_key;
 #ifdef CONFIG_MEM_ALLOC_PROFILING
 	struct alloc_tag		*alloc_tag;
 #endif
@@ -138,23 +140,29 @@ struct rhashtable_iter {
 
 int __rhashtable_init_noprof(struct rhashtable *ht,
 		    const struct rhashtable_params *params,
-		    struct lock_class_key *key);
+		    struct lock_class_key *mutex_key,
+		    struct lock_class_key *bucket_key);
 #define rhashtable_init_noprof(ht, params)				\
 ({									\
-	static struct lock_class_key __key;				\
+	static struct lock_class_key __mutex_key;			\
+	static struct lock_class_key __bucket_key;			\
 									\
-	__rhashtable_init_noprof(ht, params, &__key);			\
+	__rhashtable_init_noprof(ht, params, &__mutex_key,		\
+				 &__bucket_key);			\
 })
 #define rhashtable_init(...)	alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
 
 int __rhltable_init_noprof(struct rhltable *hlt,
 		  const struct rhashtable_params *params,
-		  struct lock_class_key *key);
+		  struct lock_class_key *mutex_key,
+		  struct lock_class_key *bucket_key);
 #define rhltable_init_noprof(hlt, params)				\
 ({									\
-	static struct lock_class_key __key;				\
+	static struct lock_class_key __mutex_key;			\
+	static struct lock_class_key __bucket_key;			\
 									\
-	__rhltable_init_noprof(hlt, params, &__key);			\
+	__rhltable_init_noprof(hlt, params, &__mutex_key,		\
+			       &__bucket_key);				\
 })
 #define rhltable_init(...)	alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
 
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index d459bef245f4..e047ad912f0e 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -189,7 +189,6 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
 	struct bucket_table *tbl = NULL;
 	size_t size;
 	int i;
-	static struct lock_class_key __key;
 
 	tbl = alloc_hooks_tag(ht->alloc_tag,
 			kvmalloc_node_align_noprof(struct_size(tbl, buckets, nbuckets),
@@ -205,7 +204,12 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
 	if (tbl == NULL)
 		return NULL;
 
-	lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", &__key, 0);
+	/*
+	 * Keep all bucket tables belonging to the same rhashtable in the
+	 * per-init-site lock class, including tables created during resize.
+	 */
+	lockdep_init_map(&tbl->dep_map, "rhashtable_bucket",
+			 ht->bucket_lock_key, 0);
 
 	tbl->size = size;
 
@@ -1162,7 +1166,8 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
  */
 int __rhashtable_init_noprof(struct rhashtable *ht,
 		    const struct rhashtable_params *params,
-		    struct lock_class_key *key)
+		    struct lock_class_key *mutex_key,
+		    struct lock_class_key *bucket_key)
 {
 	struct bucket_table *tbl;
 	size_t size;
@@ -1172,7 +1177,8 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
 		return -EINVAL;
 
 	memset(ht, 0, sizeof(*ht));
-	mutex_init_with_key(&ht->mutex, key);
+	mutex_init_with_key(&ht->mutex, mutex_key);
+	ht->bucket_lock_key = bucket_key;
 	spin_lock_init(&ht->lock);
 	memcpy(&ht->p, params, sizeof(*params));
 
@@ -1237,11 +1243,12 @@ EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
  */
 int __rhltable_init_noprof(struct rhltable *hlt,
 			   const struct rhashtable_params *params,
-			   struct lock_class_key *key)
+			   struct lock_class_key *mutex_key,
+			   struct lock_class_key *bucket_key)
 {
 	int err;
 
-	err = __rhashtable_init_noprof(&hlt->ht, params, key);
+	err = __rhashtable_init_noprof(&hlt->ht, params, mutex_key, bucket_key);
 	hlt->ht.rhlist = true;
 	return err;
 }

---
base-commit: 0131b508c0e2489eac6e121135988f6eeb716f19
change-id: 20260801-fix-rhashtable-bucket-lockdep-95e25abebeea

Best regards,
--  
quanyeyang <quanyemostima@gmail.com>



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks
  2026-08-01 10:13 [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks quanyeyang via B4 Relay
@ 2026-08-01 11:12 ` NeilBrown
  2026-08-02 10:33   ` Quanye Yang
  2026-08-14 19:27 ` kernel test robot
  1 sibling, 1 reply; 6+ messages in thread
From: NeilBrown @ 2026-08-01 11:12 UTC (permalink / raw)
  To: quanyemostima
  Cc: Thomas Graf, Herbert Xu, Andrew Morton, David S. Miller,
	linux-crypto, linux-kernel, syzbot+ef8d17bae14efb960935,
	quanyeyang

On Sat, 01 Aug 2026, quanyemostima@gmail.com wrote:
> From: quanyeyang <quanyemostima@gmail.com>
> 
> All bucket tables currently share a single lockdep class. This makes
> lockdep conflate bucket locks from unrelated rhashtable instances.
> 
> A BPF program attached to lock_release can expose this when pidfs
> inserts a pid. The tracepoint runs before lockdep removes the pidfs
> bucket lock from the task's held-lock stack. Deleting an element from
> a BPF RHASH map then acquires a bucket lock belonging to a different
> rhashtable. Since both tables use the same class, lockdep reports
> possible recursive locking.

This seems like a band-aid rather than a proper fix.

Surely attaching a BPF program to lock_release() has potential for
causing all sorts of lockdep related problems.  Any lock that the BPF
program takes can trigger something, and I find it unlikely that
rhashtable is the only part of BPF code that takes a lock.

Maybe the tracepoint needs to disable lockdep while the BPF handler is
running, or something like that.

But I would need a much stronger argument before I could be happy with
this patch.

NeilBrown


> 
> Declare a separate bucket lock class key at each rhashtable_init() and
> rhltable_init() call site, alongside the mutex class key. Store the
> bucket key in struct rhashtable so tables created during resize keep
> using the same class.
> 
> A targeted reproducer triggers the warning reliably before this change.
> After the change, the nested BPF RHASH deletion still executes, but
> lockdep no longer reports recursive locking.
> 
> Fixes: 149212f07856 ("rhashtable: add lockdep tracking to bucket bit-spin-locks.")
> Reported-by: syzbot+ef8d17bae14efb960935@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=ef8d17bae14efb960935
> Assisted-by: Cursor:GPT-5.6 Sol
> Signed-off-by: quanyeyang <quanyemostima@gmail.com>
> ---
>  include/linux/rhashtable-types.h | 20 ++++++++++++++------
>  lib/rhashtable.c                 | 19 +++++++++++++------
>  2 files changed, 27 insertions(+), 12 deletions(-)
> 
> diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
> index 57c11ec9dc64..4dea91a49ec8 100644
> --- a/include/linux/rhashtable-types.h
> +++ b/include/linux/rhashtable-types.h
> @@ -82,6 +82,7 @@ struct rhashtable_params {
>   * @mutex: Mutex to protect current/future table swapping
>   * @lock: Spin lock to protect walker list
>   * @nelems: Number of elements in table
> + * @bucket_lock_key: Per-init-site lockdep class for bucket bit-locks
>   */
>  struct rhashtable {
>  	struct bucket_table __rcu	*tbl;
> @@ -94,6 +95,7 @@ struct rhashtable {
>  	struct mutex                    mutex;
>  	spinlock_t			lock;
>  	atomic_t			nelems;
> +	struct lock_class_key		*bucket_lock_key;
>  #ifdef CONFIG_MEM_ALLOC_PROFILING
>  	struct alloc_tag		*alloc_tag;
>  #endif
> @@ -138,23 +140,29 @@ struct rhashtable_iter {
>  
>  int __rhashtable_init_noprof(struct rhashtable *ht,
>  		    const struct rhashtable_params *params,
> -		    struct lock_class_key *key);
> +		    struct lock_class_key *mutex_key,
> +		    struct lock_class_key *bucket_key);
>  #define rhashtable_init_noprof(ht, params)				\
>  ({									\
> -	static struct lock_class_key __key;				\
> +	static struct lock_class_key __mutex_key;			\
> +	static struct lock_class_key __bucket_key;			\
>  									\
> -	__rhashtable_init_noprof(ht, params, &__key);			\
> +	__rhashtable_init_noprof(ht, params, &__mutex_key,		\
> +				 &__bucket_key);			\
>  })
>  #define rhashtable_init(...)	alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
>  
>  int __rhltable_init_noprof(struct rhltable *hlt,
>  		  const struct rhashtable_params *params,
> -		  struct lock_class_key *key);
> +		  struct lock_class_key *mutex_key,
> +		  struct lock_class_key *bucket_key);
>  #define rhltable_init_noprof(hlt, params)				\
>  ({									\
> -	static struct lock_class_key __key;				\
> +	static struct lock_class_key __mutex_key;			\
> +	static struct lock_class_key __bucket_key;			\
>  									\
> -	__rhltable_init_noprof(hlt, params, &__key);			\
> +	__rhltable_init_noprof(hlt, params, &__mutex_key,		\
> +			       &__bucket_key);				\
>  })
>  #define rhltable_init(...)	alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
>  
> diff --git a/lib/rhashtable.c b/lib/rhashtable.c
> index d459bef245f4..e047ad912f0e 100644
> --- a/lib/rhashtable.c
> +++ b/lib/rhashtable.c
> @@ -189,7 +189,6 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
>  	struct bucket_table *tbl = NULL;
>  	size_t size;
>  	int i;
> -	static struct lock_class_key __key;
>  
>  	tbl = alloc_hooks_tag(ht->alloc_tag,
>  			kvmalloc_node_align_noprof(struct_size(tbl, buckets, nbuckets),
> @@ -205,7 +204,12 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
>  	if (tbl == NULL)
>  		return NULL;
>  
> -	lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", &__key, 0);
> +	/*
> +	 * Keep all bucket tables belonging to the same rhashtable in the
> +	 * per-init-site lock class, including tables created during resize.
> +	 */
> +	lockdep_init_map(&tbl->dep_map, "rhashtable_bucket",
> +			 ht->bucket_lock_key, 0);
>  
>  	tbl->size = size;
>  
> @@ -1162,7 +1166,8 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
>   */
>  int __rhashtable_init_noprof(struct rhashtable *ht,
>  		    const struct rhashtable_params *params,
> -		    struct lock_class_key *key)
> +		    struct lock_class_key *mutex_key,
> +		    struct lock_class_key *bucket_key)
>  {
>  	struct bucket_table *tbl;
>  	size_t size;
> @@ -1172,7 +1177,8 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
>  		return -EINVAL;
>  
>  	memset(ht, 0, sizeof(*ht));
> -	mutex_init_with_key(&ht->mutex, key);
> +	mutex_init_with_key(&ht->mutex, mutex_key);
> +	ht->bucket_lock_key = bucket_key;
>  	spin_lock_init(&ht->lock);
>  	memcpy(&ht->p, params, sizeof(*params));
>  
> @@ -1237,11 +1243,12 @@ EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
>   */
>  int __rhltable_init_noprof(struct rhltable *hlt,
>  			   const struct rhashtable_params *params,
> -			   struct lock_class_key *key)
> +			   struct lock_class_key *mutex_key,
> +			   struct lock_class_key *bucket_key)
>  {
>  	int err;
>  
> -	err = __rhashtable_init_noprof(&hlt->ht, params, key);
> +	err = __rhashtable_init_noprof(&hlt->ht, params, mutex_key, bucket_key);
>  	hlt->ht.rhlist = true;
>  	return err;
>  }
> 
> ---
> base-commit: 0131b508c0e2489eac6e121135988f6eeb716f19
> change-id: 20260801-fix-rhashtable-bucket-lockdep-95e25abebeea
> 
> Best regards,
> --  
> quanyeyang <quanyemostima@gmail.com>
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks
  2026-08-01 11:12 ` NeilBrown
@ 2026-08-02 10:33   ` Quanye Yang
  2026-08-03  2:00     ` NeilBrown
  0 siblings, 1 reply; 6+ messages in thread
From: Quanye Yang @ 2026-08-02 10:33 UTC (permalink / raw)
  To: NeilBrown
  Cc: Thomas Graf, Herbert Xu, Andrew Morton, David S. Miller,
	linux-crypto, linux-kernel, syzbot+ef8d17bae14efb960935

On Sat, Aug 01, 2026 at 07:12:00PM +0000, NeilBrown wrote:
> This seems like a band-aid rather than a proper fix.
>
> Surely attaching a BPF program to lock_release() has potential for
> causing all sorts of lockdep related problems.  Any lock that the BPF
> program takes can trigger something, and I find it unlikely that
> rhashtable is the only part of BPF code that takes a lock.
>
> Maybe the tracepoint needs to disable lockdep while the BPF handler is
> running, or something like that.
>
> But I would need a much stronger argument before I could be happy with
> this patch.

Thanks for the review.

I agree that attaching BPF to lock_release() is a sharp edge: the
tracepoint runs before __lock_release(), so the lock is still on the
lockdep held stack, and any lock taken by the BPF program becomes a
dependency edge.  Whether that instrumentation path should be isolated
from lockdep is a broader question, and I don't claim this patch solves
it.

But the syzbot warning at hand is not BPF-specific.  It is a false
positive from modeling every rhashtable bucket lock with one global
lock_class_key.  Different rhashtable instances have different physical
bitlocks; nesting them is not recursive locking of the same lock.

I can reproduce the same "possible recursive locking detected" without
any BPF / lock tracepoint:

  1. init two tables at distinct rhashtable_init() call sites (ht_a, ht_b)
  2. prefill so the insert path walks a non-empty bucket chain
  3. in ht_a's obj_cmpfn (called under ht_a's bucket bitlock), call
     rhashtable_lookup_insert_key() on ht_b

That is enough to hit the warning on an unpatched kernel.  So disabling
lockdep around the BPF handler would only silence one trigger for this
class-modeling bug; it would not fix the underlying incorrect lock class
sharing, and it would also hide real lock-order problems on that path
(including the callback-under-bucket-lock cases that 149212f07856 wanted
lockdep to see).

The per-init-site bucket key follows the same approach as 060d4e94b8d4
did for ht->mutex: keep one class per init site (and across resize of
that table via SINGLE_DEPTH_NESTING), rather than one class for the
entire kernel.

Happy to share the small local reproducer if that helps.

On Sat, Aug 1, 2026 at 7:12 PM NeilBrown <neilb@ownmail.net> wrote:
>
> On Sat, 01 Aug 2026, quanyemostima@gmail.com wrote:
> > From: quanyeyang <quanyemostima@gmail.com>
> >
> > All bucket tables currently share a single lockdep class. This makes
> > lockdep conflate bucket locks from unrelated rhashtable instances.
> >
> > A BPF program attached to lock_release can expose this when pidfs
> > inserts a pid. The tracepoint runs before lockdep removes the pidfs
> > bucket lock from the task's held-lock stack. Deleting an element from
> > a BPF RHASH map then acquires a bucket lock belonging to a different
> > rhashtable. Since both tables use the same class, lockdep reports
> > possible recursive locking.
>
> This seems like a band-aid rather than a proper fix.
>
> Surely attaching a BPF program to lock_release() has potential for
> causing all sorts of lockdep related problems.  Any lock that the BPF
> program takes can trigger something, and I find it unlikely that
> rhashtable is the only part of BPF code that takes a lock.
>
> Maybe the tracepoint needs to disable lockdep while the BPF handler is
> running, or something like that.
>
> But I would need a much stronger argument before I could be happy with
> this patch.
>
> NeilBrown
>
>
> >
> > Declare a separate bucket lock class key at each rhashtable_init() and
> > rhltable_init() call site, alongside the mutex class key. Store the
> > bucket key in struct rhashtable so tables created during resize keep
> > using the same class.
> >
> > A targeted reproducer triggers the warning reliably before this change.
> > After the change, the nested BPF RHASH deletion still executes, but
> > lockdep no longer reports recursive locking.
> >
> > Fixes: 149212f07856 ("rhashtable: add lockdep tracking to bucket bit-spin-locks.")
> > Reported-by: syzbot+ef8d17bae14efb960935@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=ef8d17bae14efb960935
> > Assisted-by: Cursor:GPT-5.6 Sol
> > Signed-off-by: quanyeyang <quanyemostima@gmail.com>
> > ---
> >  include/linux/rhashtable-types.h | 20 ++++++++++++++------
> >  lib/rhashtable.c                 | 19 +++++++++++++------
> >  2 files changed, 27 insertions(+), 12 deletions(-)
> >
> > diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
> > index 57c11ec9dc64..4dea91a49ec8 100644
> > --- a/include/linux/rhashtable-types.h
> > +++ b/include/linux/rhashtable-types.h
> > @@ -82,6 +82,7 @@ struct rhashtable_params {
> >   * @mutex: Mutex to protect current/future table swapping
> >   * @lock: Spin lock to protect walker list
> >   * @nelems: Number of elements in table
> > + * @bucket_lock_key: Per-init-site lockdep class for bucket bit-locks
> >   */
> >  struct rhashtable {
> >       struct bucket_table __rcu       *tbl;
> > @@ -94,6 +95,7 @@ struct rhashtable {
> >       struct mutex                    mutex;
> >       spinlock_t                      lock;
> >       atomic_t                        nelems;
> > +     struct lock_class_key           *bucket_lock_key;
> >  #ifdef CONFIG_MEM_ALLOC_PROFILING
> >       struct alloc_tag                *alloc_tag;
> >  #endif
> > @@ -138,23 +140,29 @@ struct rhashtable_iter {
> >
> >  int __rhashtable_init_noprof(struct rhashtable *ht,
> >                   const struct rhashtable_params *params,
> > -                 struct lock_class_key *key);
> > +                 struct lock_class_key *mutex_key,
> > +                 struct lock_class_key *bucket_key);
> >  #define rhashtable_init_noprof(ht, params)                           \
> >  ({                                                                   \
> > -     static struct lock_class_key __key;                             \
> > +     static struct lock_class_key __mutex_key;                       \
> > +     static struct lock_class_key __bucket_key;                      \
> >                                                                       \
> > -     __rhashtable_init_noprof(ht, params, &__key);                   \
> > +     __rhashtable_init_noprof(ht, params, &__mutex_key,              \
> > +                              &__bucket_key);                        \
> >  })
> >  #define rhashtable_init(...) alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
> >
> >  int __rhltable_init_noprof(struct rhltable *hlt,
> >                 const struct rhashtable_params *params,
> > -               struct lock_class_key *key);
> > +               struct lock_class_key *mutex_key,
> > +               struct lock_class_key *bucket_key);
> >  #define rhltable_init_noprof(hlt, params)                            \
> >  ({                                                                   \
> > -     static struct lock_class_key __key;                             \
> > +     static struct lock_class_key __mutex_key;                       \
> > +     static struct lock_class_key __bucket_key;                      \
> >                                                                       \
> > -     __rhltable_init_noprof(hlt, params, &__key);                    \
> > +     __rhltable_init_noprof(hlt, params, &__mutex_key,               \
> > +                            &__bucket_key);                          \
> >  })
> >  #define rhltable_init(...)   alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
> >
> > diff --git a/lib/rhashtable.c b/lib/rhashtable.c
> > index d459bef245f4..e047ad912f0e 100644
> > --- a/lib/rhashtable.c
> > +++ b/lib/rhashtable.c
> > @@ -189,7 +189,6 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
> >       struct bucket_table *tbl = NULL;
> >       size_t size;
> >       int i;
> > -     static struct lock_class_key __key;
> >
> >       tbl = alloc_hooks_tag(ht->alloc_tag,
> >                       kvmalloc_node_align_noprof(struct_size(tbl, buckets, nbuckets),
> > @@ -205,7 +204,12 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
> >       if (tbl == NULL)
> >               return NULL;
> >
> > -     lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", &__key, 0);
> > +     /*
> > +      * Keep all bucket tables belonging to the same rhashtable in the
> > +      * per-init-site lock class, including tables created during resize.
> > +      */
> > +     lockdep_init_map(&tbl->dep_map, "rhashtable_bucket",
> > +                      ht->bucket_lock_key, 0);
> >
> >       tbl->size = size;
> >
> > @@ -1162,7 +1166,8 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
> >   */
> >  int __rhashtable_init_noprof(struct rhashtable *ht,
> >                   const struct rhashtable_params *params,
> > -                 struct lock_class_key *key)
> > +                 struct lock_class_key *mutex_key,
> > +                 struct lock_class_key *bucket_key)
> >  {
> >       struct bucket_table *tbl;
> >       size_t size;
> > @@ -1172,7 +1177,8 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
> >               return -EINVAL;
> >
> >       memset(ht, 0, sizeof(*ht));
> > -     mutex_init_with_key(&ht->mutex, key);
> > +     mutex_init_with_key(&ht->mutex, mutex_key);
> > +     ht->bucket_lock_key = bucket_key;
> >       spin_lock_init(&ht->lock);
> >       memcpy(&ht->p, params, sizeof(*params));
> >
> > @@ -1237,11 +1243,12 @@ EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
> >   */
> >  int __rhltable_init_noprof(struct rhltable *hlt,
> >                          const struct rhashtable_params *params,
> > -                        struct lock_class_key *key)
> > +                        struct lock_class_key *mutex_key,
> > +                        struct lock_class_key *bucket_key)
> >  {
> >       int err;
> >
> > -     err = __rhashtable_init_noprof(&hlt->ht, params, key);
> > +     err = __rhashtable_init_noprof(&hlt->ht, params, mutex_key, bucket_key);
> >       hlt->ht.rhlist = true;
> >       return err;
> >  }
> >
> > ---
> > base-commit: 0131b508c0e2489eac6e121135988f6eeb716f19
> > change-id: 20260801-fix-rhashtable-bucket-lockdep-95e25abebeea
> >
> > Best regards,
> > --
> > quanyeyang <quanyemostima@gmail.com>
> >
> >
> >
> >
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks
  2026-08-02 10:33   ` Quanye Yang
@ 2026-08-03  2:00     ` NeilBrown
  2026-08-03 14:38       ` Quanye Yang
  0 siblings, 1 reply; 6+ messages in thread
From: NeilBrown @ 2026-08-03  2:00 UTC (permalink / raw)
  To: Quanye Yang
  Cc: Thomas Graf, Herbert Xu, Andrew Morton, David S. Miller,
	linux-crypto, linux-kernel, syzbot+ef8d17bae14efb960935

On Sun, 02 Aug 2026, Quanye Yang wrote:
> On Sat, Aug 01, 2026 at 07:12:00PM +0000, NeilBrown wrote:
> > This seems like a band-aid rather than a proper fix.
> >
> > Surely attaching a BPF program to lock_release() has potential for
> > causing all sorts of lockdep related problems.  Any lock that the BPF
> > program takes can trigger something, and I find it unlikely that
> > rhashtable is the only part of BPF code that takes a lock.
> >
> > Maybe the tracepoint needs to disable lockdep while the BPF handler is
> > running, or something like that.
> >
> > But I would need a much stronger argument before I could be happy with
> > this patch.
> 
> Thanks for the review.
> 
> I agree that attaching BPF to lock_release() is a sharp edge: the
> tracepoint runs before __lock_release(), so the lock is still on the
> lockdep held stack, and any lock taken by the BPF program becomes a
> dependency edge.  Whether that instrumentation path should be isolated
> from lockdep is a broader question, and I don't claim this patch solves
> it.
> 
> But the syzbot warning at hand is not BPF-specific.  It is a false
> positive from modeling every rhashtable bucket lock with one global
> lock_class_key.  Different rhashtable instances have different physical
> bitlocks; nesting them is not recursive locking of the same lock.

This is common practice in the kernel.
All dentries for all filesystems have a d_lock with the same lock_class.
All block devices have a bd_holder_lock mutex with the same lock_class.
All kobjects have a list_lock with the same lock_class.

> 
> I can reproduce the same "possible recursive locking detected" without
> any BPF / lock tracepoint:
> 
>   1. init two tables at distinct rhashtable_init() call sites (ht_a, ht_b)
>   2. prefill so the insert path walks a non-empty bucket chain
>   3. in ht_a's obj_cmpfn (called under ht_a's bucket bitlock), call
>      rhashtable_lookup_insert_key() on ht_b

Yes you *can* do that, but why *would* you do that?
The obj_cmpfn is meant to be an idempotent compare function.
We make no particular promises about when it will be called.
So making a change to anything in that function is ill-advised at best.
I don't think we have any interest in making change which would allow
an obj_cmpfn() to make changes to a different rhashtable.

> 
> That is enough to hit the warning on an unpatched kernel.  So disabling
> lockdep around the BPF handler would only silence one trigger for this
> class-modeling bug; it would not fix the underlying incorrect lock class
> sharing, and it would also hide real lock-order problems on that path
> (including the callback-under-bucket-lock cases that 149212f07856 wanted
> lockdep to see).

I think the main reason we added the lockdep tracking was to justify
that switching from spinlocks to bitlock didn't lose anything important.
It wouldn't be completely inappropriate to take a lock in an obj_cmpfn,
but I wouldn't normally expect it.

> 
> The per-init-site bucket key follows the same approach as 060d4e94b8d4
> did for ht->mutex: keep one class per init site (and across resize of
> that table via SINGLE_DEPTH_NESTING), rather than one class for the
> entire kernel.

Hmmm.. I think that patch might have been a poor choice.

Commit 09ae540e1d5c ("rhashtable: drop ht->mutex in rhashtable_free_and_destroy()")

landed about the same time and removed the problem instead of hiding it.

NeilBrown


> 
> Happy to share the small local reproducer if that helps.
> 
> On Sat, Aug 1, 2026 at 7:12 PM NeilBrown <neilb@ownmail.net> wrote:
> >
> > On Sat, 01 Aug 2026, quanyemostima@gmail.com wrote:
> > > From: quanyeyang <quanyemostima@gmail.com>
> > >
> > > All bucket tables currently share a single lockdep class. This makes
> > > lockdep conflate bucket locks from unrelated rhashtable instances.
> > >
> > > A BPF program attached to lock_release can expose this when pidfs
> > > inserts a pid. The tracepoint runs before lockdep removes the pidfs
> > > bucket lock from the task's held-lock stack. Deleting an element from
> > > a BPF RHASH map then acquires a bucket lock belonging to a different
> > > rhashtable. Since both tables use the same class, lockdep reports
> > > possible recursive locking.
> >
> > This seems like a band-aid rather than a proper fix.
> >
> > Surely attaching a BPF program to lock_release() has potential for
> > causing all sorts of lockdep related problems.  Any lock that the BPF
> > program takes can trigger something, and I find it unlikely that
> > rhashtable is the only part of BPF code that takes a lock.
> >
> > Maybe the tracepoint needs to disable lockdep while the BPF handler is
> > running, or something like that.
> >
> > But I would need a much stronger argument before I could be happy with
> > this patch.
> >
> > NeilBrown
> >
> >
> > >
> > > Declare a separate bucket lock class key at each rhashtable_init() and
> > > rhltable_init() call site, alongside the mutex class key. Store the
> > > bucket key in struct rhashtable so tables created during resize keep
> > > using the same class.
> > >
> > > A targeted reproducer triggers the warning reliably before this change.
> > > After the change, the nested BPF RHASH deletion still executes, but
> > > lockdep no longer reports recursive locking.
> > >
> > > Fixes: 149212f07856 ("rhashtable: add lockdep tracking to bucket bit-spin-locks.")
> > > Reported-by: syzbot+ef8d17bae14efb960935@syzkaller.appspotmail.com
> > > Closes: https://syzkaller.appspot.com/bug?extid=ef8d17bae14efb960935
> > > Assisted-by: Cursor:GPT-5.6 Sol
> > > Signed-off-by: quanyeyang <quanyemostima@gmail.com>
> > > ---
> > >  include/linux/rhashtable-types.h | 20 ++++++++++++++------
> > >  lib/rhashtable.c                 | 19 +++++++++++++------
> > >  2 files changed, 27 insertions(+), 12 deletions(-)
> > >
> > > diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
> > > index 57c11ec9dc64..4dea91a49ec8 100644
> > > --- a/include/linux/rhashtable-types.h
> > > +++ b/include/linux/rhashtable-types.h
> > > @@ -82,6 +82,7 @@ struct rhashtable_params {
> > >   * @mutex: Mutex to protect current/future table swapping
> > >   * @lock: Spin lock to protect walker list
> > >   * @nelems: Number of elements in table
> > > + * @bucket_lock_key: Per-init-site lockdep class for bucket bit-locks
> > >   */
> > >  struct rhashtable {
> > >       struct bucket_table __rcu       *tbl;
> > > @@ -94,6 +95,7 @@ struct rhashtable {
> > >       struct mutex                    mutex;
> > >       spinlock_t                      lock;
> > >       atomic_t                        nelems;
> > > +     struct lock_class_key           *bucket_lock_key;
> > >  #ifdef CONFIG_MEM_ALLOC_PROFILING
> > >       struct alloc_tag                *alloc_tag;
> > >  #endif
> > > @@ -138,23 +140,29 @@ struct rhashtable_iter {
> > >
> > >  int __rhashtable_init_noprof(struct rhashtable *ht,
> > >                   const struct rhashtable_params *params,
> > > -                 struct lock_class_key *key);
> > > +                 struct lock_class_key *mutex_key,
> > > +                 struct lock_class_key *bucket_key);
> > >  #define rhashtable_init_noprof(ht, params)                           \
> > >  ({                                                                   \
> > > -     static struct lock_class_key __key;                             \
> > > +     static struct lock_class_key __mutex_key;                       \
> > > +     static struct lock_class_key __bucket_key;                      \
> > >                                                                       \
> > > -     __rhashtable_init_noprof(ht, params, &__key);                   \
> > > +     __rhashtable_init_noprof(ht, params, &__mutex_key,              \
> > > +                              &__bucket_key);                        \
> > >  })
> > >  #define rhashtable_init(...) alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
> > >
> > >  int __rhltable_init_noprof(struct rhltable *hlt,
> > >                 const struct rhashtable_params *params,
> > > -               struct lock_class_key *key);
> > > +               struct lock_class_key *mutex_key,
> > > +               struct lock_class_key *bucket_key);
> > >  #define rhltable_init_noprof(hlt, params)                            \
> > >  ({                                                                   \
> > > -     static struct lock_class_key __key;                             \
> > > +     static struct lock_class_key __mutex_key;                       \
> > > +     static struct lock_class_key __bucket_key;                      \
> > >                                                                       \
> > > -     __rhltable_init_noprof(hlt, params, &__key);                    \
> > > +     __rhltable_init_noprof(hlt, params, &__mutex_key,               \
> > > +                            &__bucket_key);                          \
> > >  })
> > >  #define rhltable_init(...)   alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
> > >
> > > diff --git a/lib/rhashtable.c b/lib/rhashtable.c
> > > index d459bef245f4..e047ad912f0e 100644
> > > --- a/lib/rhashtable.c
> > > +++ b/lib/rhashtable.c
> > > @@ -189,7 +189,6 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
> > >       struct bucket_table *tbl = NULL;
> > >       size_t size;
> > >       int i;
> > > -     static struct lock_class_key __key;
> > >
> > >       tbl = alloc_hooks_tag(ht->alloc_tag,
> > >                       kvmalloc_node_align_noprof(struct_size(tbl, buckets, nbuckets),
> > > @@ -205,7 +204,12 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
> > >       if (tbl == NULL)
> > >               return NULL;
> > >
> > > -     lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", &__key, 0);
> > > +     /*
> > > +      * Keep all bucket tables belonging to the same rhashtable in the
> > > +      * per-init-site lock class, including tables created during resize.
> > > +      */
> > > +     lockdep_init_map(&tbl->dep_map, "rhashtable_bucket",
> > > +                      ht->bucket_lock_key, 0);
> > >
> > >       tbl->size = size;
> > >
> > > @@ -1162,7 +1166,8 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
> > >   */
> > >  int __rhashtable_init_noprof(struct rhashtable *ht,
> > >                   const struct rhashtable_params *params,
> > > -                 struct lock_class_key *key)
> > > +                 struct lock_class_key *mutex_key,
> > > +                 struct lock_class_key *bucket_key)
> > >  {
> > >       struct bucket_table *tbl;
> > >       size_t size;
> > > @@ -1172,7 +1177,8 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
> > >               return -EINVAL;
> > >
> > >       memset(ht, 0, sizeof(*ht));
> > > -     mutex_init_with_key(&ht->mutex, key);
> > > +     mutex_init_with_key(&ht->mutex, mutex_key);
> > > +     ht->bucket_lock_key = bucket_key;
> > >       spin_lock_init(&ht->lock);
> > >       memcpy(&ht->p, params, sizeof(*params));
> > >
> > > @@ -1237,11 +1243,12 @@ EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
> > >   */
> > >  int __rhltable_init_noprof(struct rhltable *hlt,
> > >                          const struct rhashtable_params *params,
> > > -                        struct lock_class_key *key)
> > > +                        struct lock_class_key *mutex_key,
> > > +                        struct lock_class_key *bucket_key)
> > >  {
> > >       int err;
> > >
> > > -     err = __rhashtable_init_noprof(&hlt->ht, params, key);
> > > +     err = __rhashtable_init_noprof(&hlt->ht, params, mutex_key, bucket_key);
> > >       hlt->ht.rhlist = true;
> > >       return err;
> > >  }
> > >
> > > ---
> > > base-commit: 0131b508c0e2489eac6e121135988f6eeb716f19
> > > change-id: 20260801-fix-rhashtable-bucket-lockdep-95e25abebeea
> > >
> > > Best regards,
> > > --
> > > quanyeyang <quanyemostima@gmail.com>
> > >
> > >
> > >
> > >
> >
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks
  2026-08-03  2:00     ` NeilBrown
@ 2026-08-03 14:38       ` Quanye Yang
  0 siblings, 0 replies; 6+ messages in thread
From: Quanye Yang @ 2026-08-03 14:38 UTC (permalink / raw)
  To: NeilBrown
  Cc: Thomas Graf, Herbert Xu, Andrew Morton, David S. Miller,
	linux-crypto, linux-kernel, syzbot+ef8d17bae14efb960935

On Mon, 03 Aug 2026, NeilBrown wrote:
> This is common practice in the kernel.
> All dentries for all filesystems have a d_lock with the same lock_class.
> All block devices have a bd_holder_lock mutex with the same lock_class.
> All kobjects have a list_lock with the same lock_class.

Fair enough — that matches d_lock / bd_holder_lock / kobject list_lock.
The per-init-site split was the wrong tool here.

> The obj_cmpfn is meant to be an idempotent compare function.
> We make no particular promises about when it will be called.

Right — the obj_cmpfn reproducer isn't a realistic case to shape the
lock modeling around.

> Commit 09ae540e1d5c ... removed the problem instead of hiding it.

That's the takeaway: remove the problem rather than paper over the
class modeling.

So I'm dropping this rhashtable patch, and taking the direction you
suggested — disable lockdep around the BPF handler on lock_release — as
a separate RFC:

https://lore.kernel.org/all/20260803-fix-lock-tracepoint-bpf-lockdep-v1-1-91fb7afb526a@gmail.com/

Thanks for the review.

quanyeyang

On Mon, Aug 3, 2026 at 10:00 AM NeilBrown <neilb@ownmail.net> wrote:
>
> On Sun, 02 Aug 2026, Quanye Yang wrote:
> > On Sat, Aug 01, 2026 at 07:12:00PM +0000, NeilBrown wrote:
> > > This seems like a band-aid rather than a proper fix.
> > >
> > > Surely attaching a BPF program to lock_release() has potential for
> > > causing all sorts of lockdep related problems.  Any lock that the BPF
> > > program takes can trigger something, and I find it unlikely that
> > > rhashtable is the only part of BPF code that takes a lock.
> > >
> > > Maybe the tracepoint needs to disable lockdep while the BPF handler is
> > > running, or something like that.
> > >
> > > But I would need a much stronger argument before I could be happy with
> > > this patch.
> >
> > Thanks for the review.
> >
> > I agree that attaching BPF to lock_release() is a sharp edge: the
> > tracepoint runs before __lock_release(), so the lock is still on the
> > lockdep held stack, and any lock taken by the BPF program becomes a
> > dependency edge.  Whether that instrumentation path should be isolated
> > from lockdep is a broader question, and I don't claim this patch solves
> > it.
> >
> > But the syzbot warning at hand is not BPF-specific.  It is a false
> > positive from modeling every rhashtable bucket lock with one global
> > lock_class_key.  Different rhashtable instances have different physical
> > bitlocks; nesting them is not recursive locking of the same lock.
>
> This is common practice in the kernel.
> All dentries for all filesystems have a d_lock with the same lock_class.
> All block devices have a bd_holder_lock mutex with the same lock_class.
> All kobjects have a list_lock with the same lock_class.
>
> >
> > I can reproduce the same "possible recursive locking detected" without
> > any BPF / lock tracepoint:
> >
> >   1. init two tables at distinct rhashtable_init() call sites (ht_a, ht_b)
> >   2. prefill so the insert path walks a non-empty bucket chain
> >   3. in ht_a's obj_cmpfn (called under ht_a's bucket bitlock), call
> >      rhashtable_lookup_insert_key() on ht_b
>
> Yes you *can* do that, but why *would* you do that?
> The obj_cmpfn is meant to be an idempotent compare function.
> We make no particular promises about when it will be called.
> So making a change to anything in that function is ill-advised at best.
> I don't think we have any interest in making change which would allow
> an obj_cmpfn() to make changes to a different rhashtable.
>
> >
> > That is enough to hit the warning on an unpatched kernel.  So disabling
> > lockdep around the BPF handler would only silence one trigger for this
> > class-modeling bug; it would not fix the underlying incorrect lock class
> > sharing, and it would also hide real lock-order problems on that path
> > (including the callback-under-bucket-lock cases that 149212f07856 wanted
> > lockdep to see).
>
> I think the main reason we added the lockdep tracking was to justify
> that switching from spinlocks to bitlock didn't lose anything important.
> It wouldn't be completely inappropriate to take a lock in an obj_cmpfn,
> but I wouldn't normally expect it.
>
> >
> > The per-init-site bucket key follows the same approach as 060d4e94b8d4
> > did for ht->mutex: keep one class per init site (and across resize of
> > that table via SINGLE_DEPTH_NESTING), rather than one class for the
> > entire kernel.
>
> Hmmm.. I think that patch might have been a poor choice.
>
> Commit 09ae540e1d5c ("rhashtable: drop ht->mutex in rhashtable_free_and_destroy()")
>
> landed about the same time and removed the problem instead of hiding it.
>
> NeilBrown
>
>
> >
> > Happy to share the small local reproducer if that helps.
> >
> > On Sat, Aug 1, 2026 at 7:12 PM NeilBrown <neilb@ownmail.net> wrote:
> > >
> > > On Sat, 01 Aug 2026, quanyemostima@gmail.com wrote:
> > > > From: quanyeyang <quanyemostima@gmail.com>
> > > >
> > > > All bucket tables currently share a single lockdep class. This makes
> > > > lockdep conflate bucket locks from unrelated rhashtable instances.
> > > >
> > > > A BPF program attached to lock_release can expose this when pidfs
> > > > inserts a pid. The tracepoint runs before lockdep removes the pidfs
> > > > bucket lock from the task's held-lock stack. Deleting an element from
> > > > a BPF RHASH map then acquires a bucket lock belonging to a different
> > > > rhashtable. Since both tables use the same class, lockdep reports
> > > > possible recursive locking.
> > >
> > > This seems like a band-aid rather than a proper fix.
> > >
> > > Surely attaching a BPF program to lock_release() has potential for
> > > causing all sorts of lockdep related problems.  Any lock that the BPF
> > > program takes can trigger something, and I find it unlikely that
> > > rhashtable is the only part of BPF code that takes a lock.
> > >
> > > Maybe the tracepoint needs to disable lockdep while the BPF handler is
> > > running, or something like that.
> > >
> > > But I would need a much stronger argument before I could be happy with
> > > this patch.
> > >
> > > NeilBrown
> > >
> > >
> > > >
> > > > Declare a separate bucket lock class key at each rhashtable_init() and
> > > > rhltable_init() call site, alongside the mutex class key. Store the
> > > > bucket key in struct rhashtable so tables created during resize keep
> > > > using the same class.
> > > >
> > > > A targeted reproducer triggers the warning reliably before this change.
> > > > After the change, the nested BPF RHASH deletion still executes, but
> > > > lockdep no longer reports recursive locking.
> > > >
> > > > Fixes: 149212f07856 ("rhashtable: add lockdep tracking to bucket bit-spin-locks.")
> > > > Reported-by: syzbot+ef8d17bae14efb960935@syzkaller.appspotmail.com
> > > > Closes: https://syzkaller.appspot.com/bug?extid=ef8d17bae14efb960935
> > > > Assisted-by: Cursor:GPT-5.6 Sol
> > > > Signed-off-by: quanyeyang <quanyemostima@gmail.com>
> > > > ---
> > > >  include/linux/rhashtable-types.h | 20 ++++++++++++++------
> > > >  lib/rhashtable.c                 | 19 +++++++++++++------
> > > >  2 files changed, 27 insertions(+), 12 deletions(-)
> > > >
> > > > diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
> > > > index 57c11ec9dc64..4dea91a49ec8 100644
> > > > --- a/include/linux/rhashtable-types.h
> > > > +++ b/include/linux/rhashtable-types.h
> > > > @@ -82,6 +82,7 @@ struct rhashtable_params {
> > > >   * @mutex: Mutex to protect current/future table swapping
> > > >   * @lock: Spin lock to protect walker list
> > > >   * @nelems: Number of elements in table
> > > > + * @bucket_lock_key: Per-init-site lockdep class for bucket bit-locks
> > > >   */
> > > >  struct rhashtable {
> > > >       struct bucket_table __rcu       *tbl;
> > > > @@ -94,6 +95,7 @@ struct rhashtable {
> > > >       struct mutex                    mutex;
> > > >       spinlock_t                      lock;
> > > >       atomic_t                        nelems;
> > > > +     struct lock_class_key           *bucket_lock_key;
> > > >  #ifdef CONFIG_MEM_ALLOC_PROFILING
> > > >       struct alloc_tag                *alloc_tag;
> > > >  #endif
> > > > @@ -138,23 +140,29 @@ struct rhashtable_iter {
> > > >
> > > >  int __rhashtable_init_noprof(struct rhashtable *ht,
> > > >                   const struct rhashtable_params *params,
> > > > -                 struct lock_class_key *key);
> > > > +                 struct lock_class_key *mutex_key,
> > > > +                 struct lock_class_key *bucket_key);
> > > >  #define rhashtable_init_noprof(ht, params)                           \
> > > >  ({                                                                   \
> > > > -     static struct lock_class_key __key;                             \
> > > > +     static struct lock_class_key __mutex_key;                       \
> > > > +     static struct lock_class_key __bucket_key;                      \
> > > >                                                                       \
> > > > -     __rhashtable_init_noprof(ht, params, &__key);                   \
> > > > +     __rhashtable_init_noprof(ht, params, &__mutex_key,              \
> > > > +                              &__bucket_key);                        \
> > > >  })
> > > >  #define rhashtable_init(...) alloc_hooks(rhashtable_init_noprof(__VA_ARGS__))
> > > >
> > > >  int __rhltable_init_noprof(struct rhltable *hlt,
> > > >                 const struct rhashtable_params *params,
> > > > -               struct lock_class_key *key);
> > > > +               struct lock_class_key *mutex_key,
> > > > +               struct lock_class_key *bucket_key);
> > > >  #define rhltable_init_noprof(hlt, params)                            \
> > > >  ({                                                                   \
> > > > -     static struct lock_class_key __key;                             \
> > > > +     static struct lock_class_key __mutex_key;                       \
> > > > +     static struct lock_class_key __bucket_key;                      \
> > > >                                                                       \
> > > > -     __rhltable_init_noprof(hlt, params, &__key);                    \
> > > > +     __rhltable_init_noprof(hlt, params, &__mutex_key,               \
> > > > +                            &__bucket_key);                          \
> > > >  })
> > > >  #define rhltable_init(...)   alloc_hooks(rhltable_init_noprof(__VA_ARGS__))
> > > >
> > > > diff --git a/lib/rhashtable.c b/lib/rhashtable.c
> > > > index d459bef245f4..e047ad912f0e 100644
> > > > --- a/lib/rhashtable.c
> > > > +++ b/lib/rhashtable.c
> > > > @@ -189,7 +189,6 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
> > > >       struct bucket_table *tbl = NULL;
> > > >       size_t size;
> > > >       int i;
> > > > -     static struct lock_class_key __key;
> > > >
> > > >       tbl = alloc_hooks_tag(ht->alloc_tag,
> > > >                       kvmalloc_node_align_noprof(struct_size(tbl, buckets, nbuckets),
> > > > @@ -205,7 +204,12 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
> > > >       if (tbl == NULL)
> > > >               return NULL;
> > > >
> > > > -     lockdep_init_map(&tbl->dep_map, "rhashtable_bucket", &__key, 0);
> > > > +     /*
> > > > +      * Keep all bucket tables belonging to the same rhashtable in the
> > > > +      * per-init-site lock class, including tables created during resize.
> > > > +      */
> > > > +     lockdep_init_map(&tbl->dep_map, "rhashtable_bucket",
> > > > +                      ht->bucket_lock_key, 0);
> > > >
> > > >       tbl->size = size;
> > > >
> > > > @@ -1162,7 +1166,8 @@ static u32 rhashtable_jhash2(const void *key, u32 length, u32 seed)
> > > >   */
> > > >  int __rhashtable_init_noprof(struct rhashtable *ht,
> > > >                   const struct rhashtable_params *params,
> > > > -                 struct lock_class_key *key)
> > > > +                 struct lock_class_key *mutex_key,
> > > > +                 struct lock_class_key *bucket_key)
> > > >  {
> > > >       struct bucket_table *tbl;
> > > >       size_t size;
> > > > @@ -1172,7 +1177,8 @@ int __rhashtable_init_noprof(struct rhashtable *ht,
> > > >               return -EINVAL;
> > > >
> > > >       memset(ht, 0, sizeof(*ht));
> > > > -     mutex_init_with_key(&ht->mutex, key);
> > > > +     mutex_init_with_key(&ht->mutex, mutex_key);
> > > > +     ht->bucket_lock_key = bucket_key;
> > > >       spin_lock_init(&ht->lock);
> > > >       memcpy(&ht->p, params, sizeof(*params));
> > > >
> > > > @@ -1237,11 +1243,12 @@ EXPORT_SYMBOL_GPL(__rhashtable_init_noprof);
> > > >   */
> > > >  int __rhltable_init_noprof(struct rhltable *hlt,
> > > >                          const struct rhashtable_params *params,
> > > > -                        struct lock_class_key *key)
> > > > +                        struct lock_class_key *mutex_key,
> > > > +                        struct lock_class_key *bucket_key)
> > > >  {
> > > >       int err;
> > > >
> > > > -     err = __rhashtable_init_noprof(&hlt->ht, params, key);
> > > > +     err = __rhashtable_init_noprof(&hlt->ht, params, mutex_key, bucket_key);
> > > >       hlt->ht.rhlist = true;
> > > >       return err;
> > > >  }
> > > >
> > > > ---
> > > > base-commit: 0131b508c0e2489eac6e121135988f6eeb716f19
> > > > change-id: 20260801-fix-rhashtable-bucket-lockdep-95e25abebeea
> > > >
> > > > Best regards,
> > > > --
> > > > quanyeyang <quanyemostima@gmail.com>
> > > >
> > > >
> > > >
> > > >
> > >
> >
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks
  2026-08-01 10:13 [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks quanyeyang via B4 Relay
  2026-08-01 11:12 ` NeilBrown
@ 2026-08-14 19:27 ` kernel test robot
  1 sibling, 0 replies; 6+ messages in thread
From: kernel test robot @ 2026-08-14 19:27 UTC (permalink / raw)
  To: quanyeyang via B4 Relay, Thomas Graf, Herbert Xu, Andrew Morton,
	NeilBrown, David S. Miller
  Cc: oe-kbuild-all, Linux Memory Management List, netdev, linux-crypto,
	linux-kernel, syzbot+ef8d17bae14efb960935, quanyeyang

Hi quanyeyang,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 0131b508c0e2489eac6e121135988f6eeb716f19]

url:    https://github.com/intel-lab-lkp/linux/commits/quanyeyang-via-B4-Relay/rhashtable-use-per-init-site-lockdep-classes-for-bucket-locks/20260815-014140
base:   0131b508c0e2489eac6e121135988f6eeb716f19
patch link:    https://lore.kernel.org/r/20260801-fix-rhashtable-bucket-lockdep-v1-1-15a0f8ae094c%40gmail.com
patch subject: [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks
config: alpha-allmodconfig (https://download.01.org/0day-ci/archive/20260815/202608150357.9LheVOQg-lkp@intel.com/config)
compiler: alpha-linux-gcc (GCC) 16.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260815/202608150357.9LheVOQg-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202608150357.9LheVOQg-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> Warning: lib/rhashtable.c:1170 function parameter 'mutex_key' not described in '__rhashtable_init'
>> Warning: lib/rhashtable.c:1170 function parameter 'bucket_key' not described in '__rhashtable_init'
   Warning: lib/rhashtable.c:1170 expecting prototype for rhashtable_init(). Prototype was for __rhashtable_init() instead
>> Warning: lib/rhashtable.c:1247 function parameter 'mutex_key' not described in '__rhltable_init'
>> Warning: lib/rhashtable.c:1247 function parameter 'bucket_key' not described in '__rhltable_init'
   Warning: lib/rhashtable.c:1247 expecting prototype for rhltable_init(). Prototype was for __rhltable_init() instead

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-08-14 19:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-01 10:13 [PATCH] rhashtable: use per-init-site lockdep classes for bucket locks quanyeyang via B4 Relay
2026-08-01 11:12 ` NeilBrown
2026-08-02 10:33   ` Quanye Yang
2026-08-03  2:00     ` NeilBrown
2026-08-03 14:38       ` Quanye Yang
2026-08-14 19:27 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox