All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set
@ 2026-04-19 18:19 Tejun Heo
  2026-04-20  8:44 ` Herbert Xu
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Tejun Heo @ 2026-04-19 18:19 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Thomas Graf, Andrew Morton, linux-crypto, linux-kernel

insecure_elasticity allows rhashtable inserts under raw spinlocks by
disabling the synchronous grow path. Inserts past 75% load still call
schedule_work(&ht->run_work) to kick an async resize. schedule_work()
under a raw spinlock records

  caller_lock -> pool->lock -> pi_lock -> rq->__lock

A cycle forms if any of these locks is acquired in the reverse
direction elsewhere. sched_ext, the only current user of the flag,
hits this: it holds scx_sched_lock across rhashtable inserts of
sub-schedulers, while scx_bypass() takes rq->__lock -> scx_sched_lock.
Exercising the resize path produces:

  Chain exists of:
    &pool->lock --> &rq->__lock --> scx_sched_lock

Route the kick through irq_work when insecure_elasticity is set so
schedule_work() runs from hard IRQ context with the caller's lock no
longer held.

Fixes: 73bd1227787b ("rhashtable: Restore insecure_elasticity toggle")
Signed-off-by: Tejun Heo <tj@kernel.org>
---
Herbert,

The lockdep splat described above is reproducible on sched_ext (the
only current insecure_elasticity user) and this patch clears it.
Verified with CONFIG_PROVE_LOCKING=y.

What do you think? Could also be a separate flag if you'd prefer to
keep insecure_elasticity strictly about elasticity.

Thanks.

 include/linux/rhashtable-types.h |  4 ++++
 include/linux/rhashtable.h       | 17 +++++++++++++++++
 lib/rhashtable.c                 | 16 ++++++++++++----
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 72082428d6c6..50b70d470e02 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -12,6 +12,7 @@
 #include <linux/alloc_tag.h>
 #include <linux/atomic.h>
 #include <linux/compiler.h>
+#include <linux/irq_work_types.h>
 #include <linux/mutex.h>
 #include <linux/workqueue_types.h>

@@ -77,6 +78,8 @@ struct rhashtable_params {
  * @p: Configuration parameters
  * @rhlist: True if this is an rhltable
  * @run_work: Deferred worker to expand/shrink asynchronously
+ * @run_irq_work: Used in place of @run_work when @p.insecure_elasticity is
+ *		  set. See rhashtable_kick_deferred_worker().
  * @mutex: Mutex to protect current/future table swapping
  * @lock: Spin lock to protect walker list
  * @nelems: Number of elements in table
@@ -88,6 +91,7 @@ struct rhashtable {
 	struct rhashtable_params	p;
 	bool				rhlist;
 	struct work_struct		run_work;
+	struct irq_work			run_irq_work;
 	struct mutex                    mutex;
 	spinlock_t			lock;
 	atomic_t			nelems;
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 7def3f0f556b..300e1139cdca 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -20,6 +20,7 @@

 #include <linux/err.h>
 #include <linux/errno.h>
+#include <linux/irq_work.h>
 #include <linux/jhash.h>
 #include <linux/list_nulls.h>
 #include <linux/workqueue.h>
@@ -747,6 +748,22 @@ static __always_inline struct rhlist_head *rhltable_lookup_likely(
 	return likely(he) ? container_of(he, struct rhlist_head, rhead) : NULL;
 }

+/*
+ * Kick the deferred rehash worker. With insecure_elasticity the caller may
+ * hold a raw spinlock. schedule_work() under a raw spinlock records
+ * caller_lock -> pool->lock -> pi_lock -> rq->__lock. If any of these
+ * locks is acquired in the reverse direction elsewhere, the cycle closes.
+ * Bounce through irq_work so schedule_work() runs from hard IRQ context
+ * with the caller's lock no longer held.
+ */
+static void rhashtable_kick_deferred_worker(struct rhashtable *ht)
+{
+	if (ht->p.insecure_elasticity)
+		irq_work_queue(&ht->run_irq_work);
+	else
+		schedule_work(&ht->run_work);
+}
+
 /* Internal function, please use rhashtable_insert_fast() instead. This
  * function returns the existing element already in hashes if there is a clash,
  * otherwise it returns an error via ERR_PTR().
@@ -847,7 +864,7 @@ static __always_inline void *__rhashtable_insert_fast(
 	rht_assign_unlock(tbl, bkt, obj, flags);

 	if (rht_grow_above_75(ht, tbl))
-		schedule_work(&ht->run_work);
+		rhashtable_kick_deferred_worker(ht);

 	data = NULL;
 out:
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index fb2b7bc137ba..951e90116889 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -442,7 +442,15 @@ static void rht_deferred_worker(struct work_struct *work)
 	mutex_unlock(&ht->mutex);

 	if (err)
-		schedule_work(&ht->run_work);
+		rhashtable_kick_deferred_worker(ht);
+}
+
+static void rht_deferred_irq_work(struct irq_work *irq_work)
+{
+	struct rhashtable *ht = container_of(irq_work, struct rhashtable,
+					     run_irq_work);
+
+	schedule_work(&ht->run_work);
 }

 static int rhashtable_insert_rehash(struct rhashtable *ht,
@@ -477,7 +485,7 @@ static int rhashtable_insert_rehash(struct rhashtable *ht,
 		if (err == -EEXIST)
 			err = 0;
 	} else
-		schedule_work(&ht->run_work);
+		rhashtable_kick_deferred_worker(ht);

 	return err;

@@ -488,7 +496,7 @@ static int rhashtable_insert_rehash(struct rhashtable *ht,

 	/* Schedule async rehash to retry allocation in process context. */
 	if (err == -ENOMEM)
-		schedule_work(&ht->run_work);
+		rhashtable_kick_deferred_worker(ht);

 	return err;
 }
@@ -630,7 +638,7 @@ static void *rhashtable_try_insert(struct rhashtable *ht, const void *key,
 			rht_unlock(tbl, bkt, flags);

 			if (inserted && rht_grow_above_75(ht, tbl))
-				schedule_work(&ht->run_work);
+				rhashtable_kick_deferred_worker(ht);
 		}
 	} while (!IS_ERR_OR_NULL(new_tbl));

@@ -1085,6 +1093,8 @@ int rhashtable_init_noprof(struct rhashtable *ht,
 	RCU_INIT_POINTER(ht->tbl, tbl);

 	INIT_WORK(&ht->run_work, rht_deferred_worker);
+	if (ht->p.insecure_elasticity)
+		init_irq_work(&ht->run_irq_work, rht_deferred_irq_work);

 	return 0;
 }
@@ -1150,6 +1160,8 @@ void rhashtable_free_and_destroy(struct rhashtable *ht,
 	struct bucket_table *tbl, *next_tbl;
 	unsigned int i;

+	if (ht->p.insecure_elasticity)
+		irq_work_sync(&ht->run_irq_work);
 	cancel_work_sync(&ht->run_work);

 	mutex_lock(&ht->mutex);

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

* Re: [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set
  2026-04-19 18:19 [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set Tejun Heo
@ 2026-04-20  8:44 ` Herbert Xu
  2026-04-20 17:02   ` Tejun Heo
  2026-04-20 18:12 ` [PATCH v2] rhashtable: Bounce deferred worker kick through irq_work Tejun Heo
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Herbert Xu @ 2026-04-20  8:44 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Thomas Graf, Andrew Morton, linux-crypto, linux-kernel

On Sun, Apr 19, 2026 at 08:19:33AM -1000, Tejun Heo wrote:
>
> +/*
> + * Kick the deferred rehash worker. With insecure_elasticity the caller may
> + * hold a raw spinlock. schedule_work() under a raw spinlock records
> + * caller_lock -> pool->lock -> pi_lock -> rq->__lock. If any of these
> + * locks is acquired in the reverse direction elsewhere, the cycle closes.
> + * Bounce through irq_work so schedule_work() runs from hard IRQ context
> + * with the caller's lock no longer held.
> + */
> +static void rhashtable_kick_deferred_worker(struct rhashtable *ht)
> +{
> +	if (ht->p.insecure_elasticity)
> +		irq_work_queue(&ht->run_irq_work);
> +	else
> +		schedule_work(&ht->run_work);
> +}

Can we just do irq_work_queue unconditionally?

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

* Re: [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set
  2026-04-20  8:44 ` Herbert Xu
@ 2026-04-20 17:02   ` Tejun Heo
  0 siblings, 0 replies; 12+ messages in thread
From: Tejun Heo @ 2026-04-20 17:02 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Thomas Graf, Andrew Morton, linux-crypto, linux-kernel

On Mon, Apr 20, 2026 at 04:44:26PM +0800, Herbert Xu wrote:
> On Sun, Apr 19, 2026 at 08:19:33AM -1000, Tejun Heo wrote:
> >
> > +/*
> > + * Kick the deferred rehash worker. With insecure_elasticity the caller may
> > + * hold a raw spinlock. schedule_work() under a raw spinlock records
> > + * caller_lock -> pool->lock -> pi_lock -> rq->__lock. If any of these
> > + * locks is acquired in the reverse direction elsewhere, the cycle closes.
> > + * Bounce through irq_work so schedule_work() runs from hard IRQ context
> > + * with the caller's lock no longer held.
> > + */
> > +static void rhashtable_kick_deferred_worker(struct rhashtable *ht)
> > +{
> > +	if (ht->p.insecure_elasticity)
> > +		irq_work_queue(&ht->run_irq_work);
> > +	else
> > +		schedule_work(&ht->run_work);
> > +}
> 
> Can we just do irq_work_queue unconditionally?

Oh yeah, that works too. I'll respin the patch.

Thanks.

-- 
tejun

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

* [PATCH v2] rhashtable: Bounce deferred worker kick through irq_work
  2026-04-19 18:19 [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set Tejun Heo
  2026-04-20  8:44 ` Herbert Xu
@ 2026-04-20 18:12 ` Tejun Heo
  2026-04-21  3:02   ` Herbert Xu
  2026-04-21  6:03   ` [PATCH v3] " Tejun Heo
  2026-04-27 23:12 ` [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set kernel test robot
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 12+ messages in thread
From: Tejun Heo @ 2026-04-20 18:12 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Thomas Graf, Andrew Morton, linux-crypto, linux-kernel

Inserts past 75% load call schedule_work(&ht->run_work) to kick an
async resize. If a caller holds a raw spinlock (e.g. an
insecure_elasticity user), schedule_work() under that lock records

  caller_lock -> pool->lock -> pi_lock -> rq->__lock

A cycle forms if any of these locks is acquired in the reverse
direction elsewhere. sched_ext, the only current insecure_elasticity
user, hits this: it holds scx_sched_lock across rhashtable inserts of
sub-schedulers, while scx_bypass() takes rq->__lock -> scx_sched_lock.
Exercising the resize path produces:

  Chain exists of:
    &pool->lock --> &rq->__lock --> scx_sched_lock

Route the kick unconditionally through irq_work so schedule_work() runs
from hard IRQ context with the caller's lock no longer held.

v2: bounce unconditionally instead of gating on insecure_elasticity, as
    suggested by Herbert.

Signed-off-by: Tejun Heo <tj@kernel.org>
---
Herbert, any preference on how this should be routed?

Thanks.

 include/linux/rhashtable-types.h |  3 +++
 include/linux/rhashtable.h       |  3 ++-
 lib/rhashtable.c                 | 24 ++++++++++++++++++++----
 3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 72082428d6c6..fc2f596a6df1 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -12,6 +12,7 @@
 #include <linux/alloc_tag.h>
 #include <linux/atomic.h>
 #include <linux/compiler.h>
+#include <linux/irq_work_types.h>
 #include <linux/mutex.h>
 #include <linux/workqueue_types.h>

@@ -77,6 +78,7 @@ struct rhashtable_params {
  * @p: Configuration parameters
  * @rhlist: True if this is an rhltable
  * @run_work: Deferred worker to expand/shrink asynchronously
+ * @run_irq_work: Bounces the @run_work kick through hard IRQ context.
  * @mutex: Mutex to protect current/future table swapping
  * @lock: Spin lock to protect walker list
  * @nelems: Number of elements in table
@@ -88,6 +90,7 @@ struct rhashtable_params {
 	struct rhashtable_params	p;
 	bool				rhlist;
 	struct work_struct		run_work;
+	struct irq_work			run_irq_work;
 	struct mutex                    mutex;
 	spinlock_t			lock;
 	atomic_t			nelems;
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 7def3f0f556b..ef5230cece36 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -20,6 +20,7 @@

 #include <linux/err.h>
 #include <linux/errno.h>
+#include <linux/irq_work.h>
 #include <linux/jhash.h>
 #include <linux/list_nulls.h>
 #include <linux/workqueue.h>
@@ -847,7 +848,7 @@ static __always_inline void *__rhashtable_insert_fast(
 	rht_assign_unlock(tbl, bkt, obj, flags);

 	if (rht_grow_above_75(ht, tbl))
-		schedule_work(&ht->run_work);
+		irq_work_queue(&ht->run_irq_work);

 	data = NULL;
 out:
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index fb2b7bc137ba..218d3c1f34fb 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -442,7 +442,21 @@ static void rht_deferred_worker(struct work_struct *work)
 	mutex_unlock(&ht->mutex);

 	if (err)
-		schedule_work(&ht->run_work);
+		irq_work_queue(&ht->run_irq_work);
+}
+
+/*
+ * rhashtable can be used under raw spinlocks. Calling schedule_work()
+ * from such context can close a locking cycle through workqueue and
+ * scheduler locks. Bounce through irq_work so the schedule_work() runs
+ * from hard IRQ context with the caller's lock no longer held.
+ */
+static void rht_deferred_irq_work(struct irq_work *irq_work)
+{
+	struct rhashtable *ht = container_of(irq_work, struct rhashtable,
+					     run_irq_work);
+
+	schedule_work(&ht->run_work);
 }

 static int rhashtable_insert_rehash(struct rhashtable *ht,
@@ -477,7 +491,7 @@ static int rhashtable_insert_rehash(struct rhashtable *ht,
 		if (err == -EEXIST)
 			err = 0;
 	} else
-		schedule_work(&ht->run_work);
+		irq_work_queue(&ht->run_irq_work);

 	return err;

@@ -488,7 +502,7 @@ static int rhashtable_insert_rehash(struct rhashtable *ht,

 	/* Schedule async rehash to retry allocation in process context. */
 	if (err == -ENOMEM)
-		schedule_work(&ht->run_work);
+		irq_work_queue(&ht->run_irq_work);

 	return err;
 }
@@ -630,7 +644,7 @@ static void *rhashtable_try_insert(struct rhashtable *ht, const void *key,
 			rht_unlock(tbl, bkt, flags);

 			if (inserted && rht_grow_above_75(ht, tbl))
-				schedule_work(&ht->run_work);
+				irq_work_queue(&ht->run_irq_work);
 		}
 	} while (!IS_ERR_OR_NULL(new_tbl));

@@ -1085,6 +1099,7 @@ int rhashtable_init_noprof(struct rhashtable *ht,
 	RCU_INIT_POINTER(ht->tbl, tbl);

 	INIT_WORK(&ht->run_work, rht_deferred_worker);
+	init_irq_work(&ht->run_irq_work, rht_deferred_irq_work);

 	return 0;
 }
@@ -1150,6 +1165,7 @@ void rhashtable_free_and_destroy(struct rhashtable *ht,
 	struct bucket_table *tbl, *next_tbl;
 	unsigned int i;

+	irq_work_sync(&ht->run_irq_work);
 	cancel_work_sync(&ht->run_work);

 	mutex_lock(&ht->mutex);

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

* Re: [PATCH v2] rhashtable: Bounce deferred worker kick through irq_work
  2026-04-20 18:12 ` [PATCH v2] rhashtable: Bounce deferred worker kick through irq_work Tejun Heo
@ 2026-04-21  3:02   ` Herbert Xu
  2026-04-21  6:03   ` [PATCH v3] " Tejun Heo
  1 sibling, 0 replies; 12+ messages in thread
From: Herbert Xu @ 2026-04-21  3:02 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Thomas Graf, Andrew Morton, linux-crypto, linux-kernel

On Mon, Apr 20, 2026 at 08:12:58AM -1000, Tejun Heo wrote:
> Inserts past 75% load call schedule_work(&ht->run_work) to kick an
> async resize. If a caller holds a raw spinlock (e.g. an
> insecure_elasticity user), schedule_work() under that lock records
> 
>   caller_lock -> pool->lock -> pi_lock -> rq->__lock
> 
> A cycle forms if any of these locks is acquired in the reverse
> direction elsewhere. sched_ext, the only current insecure_elasticity
> user, hits this: it holds scx_sched_lock across rhashtable inserts of
> sub-schedulers, while scx_bypass() takes rq->__lock -> scx_sched_lock.
> Exercising the resize path produces:
> 
>   Chain exists of:
>     &pool->lock --> &rq->__lock --> scx_sched_lock
> 
> Route the kick unconditionally through irq_work so schedule_work() runs
> from hard IRQ context with the caller's lock no longer held.
> 
> v2: bounce unconditionally instead of gating on insecure_elasticity, as
>     suggested by Herbert.
> 
> Signed-off-by: Tejun Heo <tj@kernel.org>
> ---
> Herbert, any preference on how this should be routed?

Acked-by: Herbert Xu <herbert@gondor.apana.org.au>

Please feel free to take this through your tree.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

* [PATCH v3] rhashtable: Bounce deferred worker kick through irq_work
  2026-04-20 18:12 ` [PATCH v2] rhashtable: Bounce deferred worker kick through irq_work Tejun Heo
  2026-04-21  3:02   ` Herbert Xu
@ 2026-04-21  6:03   ` Tejun Heo
  2026-04-21  6:06     ` Herbert Xu
  2026-05-12  6:07     ` Hillf Danton
  1 sibling, 2 replies; 12+ messages in thread
From: Tejun Heo @ 2026-04-21  6:03 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Thomas Graf, Andrew Morton, linux-crypto, linux-kernel

Inserts past 75% load call schedule_work(&ht->run_work) to kick an
async resize. If a caller holds a raw spinlock (e.g. an
insecure_elasticity user), schedule_work() under that lock records

  caller_lock -> pool->lock -> pi_lock -> rq->__lock

A cycle forms if any of these locks is acquired in the reverse
direction elsewhere. sched_ext, the only current insecure_elasticity
user, hits this: it holds scx_sched_lock across rhashtable inserts of
sub-schedulers, while scx_bypass() takes rq->__lock -> scx_sched_lock.
Exercising the resize path produces:

  Chain exists of:
    &pool->lock --> &rq->__lock --> scx_sched_lock

Bounce the kick from the insert paths through irq_work so
schedule_work() runs from hard IRQ context with the caller's lock no
longer held. rht_deferred_worker()'s self-rearm on error stays on
schedule_work(&ht->run_work) - the worker runs in process context with
no caller lock held, and keeping the self-requeue on @run_work lets
cancel_work_sync() in rhashtable_free_and_destroy() drain it.

v3: Keep rht_deferred_worker()'s self-rearm on schedule_work(&run_work).
    Routing it through irq_work in v2 broke cancel_work_sync()'s
    self-requeue handling - an irq_work queued after irq_work_sync()
    returned but while cancel_work_sync() was still waiting could fire
    post-teardown.

v2: Bounce unconditionally instead of gating on insecure_elasticity,
    as suggested by Herbert.

Signed-off-by: Tejun Heo <tj@kernel.org>
---
Herbert, dropped your Ack on v2. v2 routed rht_deferred_worker()'s
self-rearm through irq_work, which would race with
cancel_work_sync() in rhashtable_free_and_destroy(). v3 keeps only
the insert-path kicks on irq_work; the worker's self-rearm stays on
schedule_work(&ht->run_work).

 include/linux/rhashtable-types.h |  3 +++
 include/linux/rhashtable.h       |  3 ++-
 lib/rhashtable.c                 | 31 ++++++++++++++++++++++++++++---
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 72082428d6c6..fc2f596a6df1 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -12,6 +12,7 @@
 #include <linux/alloc_tag.h>
 #include <linux/atomic.h>
 #include <linux/compiler.h>
+#include <linux/irq_work_types.h>
 #include <linux/mutex.h>
 #include <linux/workqueue_types.h>
 
@@ -77,6 +78,7 @@ struct rhashtable_params {
  * @p: Configuration parameters
  * @rhlist: True if this is an rhltable
  * @run_work: Deferred worker to expand/shrink asynchronously
+ * @run_irq_work: Bounces the @run_work kick through hard IRQ context.
  * @mutex: Mutex to protect current/future table swapping
  * @lock: Spin lock to protect walker list
  * @nelems: Number of elements in table
@@ -88,6 +90,7 @@ struct rhashtable {
 	struct rhashtable_params	p;
 	bool				rhlist;
 	struct work_struct		run_work;
+	struct irq_work			run_irq_work;
 	struct mutex                    mutex;
 	spinlock_t			lock;
 	atomic_t			nelems;
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 7def3f0f556b..ef5230cece36 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -20,6 +20,7 @@
 
 #include <linux/err.h>
 #include <linux/errno.h>
+#include <linux/irq_work.h>
 #include <linux/jhash.h>
 #include <linux/list_nulls.h>
 #include <linux/workqueue.h>
@@ -847,7 +848,7 @@ static __always_inline void *__rhashtable_insert_fast(
 	rht_assign_unlock(tbl, bkt, obj, flags);
 
 	if (rht_grow_above_75(ht, tbl))
-		schedule_work(&ht->run_work);
+		irq_work_queue(&ht->run_irq_work);
 
 	data = NULL;
 out:
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index fb2b7bc137ba..7a67ef5b67b6 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -441,10 +441,33 @@ static void rht_deferred_worker(struct work_struct *work)
 
 	mutex_unlock(&ht->mutex);
 
+	/*
+	 * Re-arm via @run_work, not @run_irq_work.
+	 * rhashtable_free_and_destroy() drains async work as irq_work_sync()
+	 * followed by cancel_work_sync(). If this site queued irq_work while
+	 * cancel_work_sync() was waiting for us, irq_work_sync() would already
+	 * have returned and the stale irq_work could fire post-teardown.
+	 * cancel_work_sync() natively handles self-requeue on @run_work.
+	 */
 	if (err)
 		schedule_work(&ht->run_work);
 }
 
+/*
+ * Insert-path callers can run under a raw spinlock (e.g. an insecure_elasticity
+ * user). Calling schedule_work() under that lock records caller_lock ->
+ * pool->lock -> pi_lock -> rq->__lock, closing a locking cycle if any of
+ * these is acquired in the reverse direction elsewhere. Bounce through
+ * irq_work so the schedule_work() runs with the caller's lock no longer held.
+ */
+static void rht_deferred_irq_work(struct irq_work *irq_work)
+{
+	struct rhashtable *ht = container_of(irq_work, struct rhashtable,
+					     run_irq_work);
+
+	schedule_work(&ht->run_work);
+}
+
 static int rhashtable_insert_rehash(struct rhashtable *ht,
 				    struct bucket_table *tbl)
 {
@@ -477,7 +500,7 @@ static int rhashtable_insert_rehash(struct rhashtable *ht,
 		if (err == -EEXIST)
 			err = 0;
 	} else
-		schedule_work(&ht->run_work);
+		irq_work_queue(&ht->run_irq_work);
 
 	return err;
 
@@ -488,7 +511,7 @@ static int rhashtable_insert_rehash(struct rhashtable *ht,
 
 	/* Schedule async rehash to retry allocation in process context. */
 	if (err == -ENOMEM)
-		schedule_work(&ht->run_work);
+		irq_work_queue(&ht->run_irq_work);
 
 	return err;
 }
@@ -630,7 +653,7 @@ static void *rhashtable_try_insert(struct rhashtable *ht, const void *key,
 			rht_unlock(tbl, bkt, flags);
 
 			if (inserted && rht_grow_above_75(ht, tbl))
-				schedule_work(&ht->run_work);
+				irq_work_queue(&ht->run_irq_work);
 		}
 	} while (!IS_ERR_OR_NULL(new_tbl));
 
@@ -1085,6 +1108,7 @@ int rhashtable_init_noprof(struct rhashtable *ht,
 	RCU_INIT_POINTER(ht->tbl, tbl);
 
 	INIT_WORK(&ht->run_work, rht_deferred_worker);
+	init_irq_work(&ht->run_irq_work, rht_deferred_irq_work);
 
 	return 0;
 }
@@ -1150,6 +1174,7 @@ void rhashtable_free_and_destroy(struct rhashtable *ht,
 	struct bucket_table *tbl, *next_tbl;
 	unsigned int i;
 
+	irq_work_sync(&ht->run_irq_work);
 	cancel_work_sync(&ht->run_work);
 
 	mutex_lock(&ht->mutex);
-- 
2.53.0


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

* Re: [PATCH v3] rhashtable: Bounce deferred worker kick through irq_work
  2026-04-21  6:03   ` [PATCH v3] " Tejun Heo
@ 2026-04-21  6:06     ` Herbert Xu
  2026-04-21  6:14       ` Tejun Heo
  2026-05-12  6:07     ` Hillf Danton
  1 sibling, 1 reply; 12+ messages in thread
From: Herbert Xu @ 2026-04-21  6:06 UTC (permalink / raw)
  To: Tejun Heo; +Cc: Thomas Graf, Andrew Morton, linux-crypto, linux-kernel

On Mon, Apr 20, 2026 at 08:03:26PM -1000, Tejun Heo wrote:
> Inserts past 75% load call schedule_work(&ht->run_work) to kick an
> async resize. If a caller holds a raw spinlock (e.g. an
> insecure_elasticity user), schedule_work() under that lock records
> 
>   caller_lock -> pool->lock -> pi_lock -> rq->__lock
> 
> A cycle forms if any of these locks is acquired in the reverse
> direction elsewhere. sched_ext, the only current insecure_elasticity
> user, hits this: it holds scx_sched_lock across rhashtable inserts of
> sub-schedulers, while scx_bypass() takes rq->__lock -> scx_sched_lock.
> Exercising the resize path produces:
> 
>   Chain exists of:
>     &pool->lock --> &rq->__lock --> scx_sched_lock
> 
> Bounce the kick from the insert paths through irq_work so
> schedule_work() runs from hard IRQ context with the caller's lock no
> longer held. rht_deferred_worker()'s self-rearm on error stays on
> schedule_work(&ht->run_work) - the worker runs in process context with
> no caller lock held, and keeping the self-requeue on @run_work lets
> cancel_work_sync() in rhashtable_free_and_destroy() drain it.
> 
> v3: Keep rht_deferred_worker()'s self-rearm on schedule_work(&run_work).
>     Routing it through irq_work in v2 broke cancel_work_sync()'s
>     self-requeue handling - an irq_work queued after irq_work_sync()
>     returned but while cancel_work_sync() was still waiting could fire
>     post-teardown.
> 
> v2: Bounce unconditionally instead of gating on insecure_elasticity,
>     as suggested by Herbert.
> 
> Signed-off-by: Tejun Heo <tj@kernel.org>
> ---
> Herbert, dropped your Ack on v2. v2 routed rht_deferred_worker()'s
> self-rearm through irq_work, which would race with
> cancel_work_sync() in rhashtable_free_and_destroy(). v3 keeps only
> the insert-path kicks on irq_work; the worker's self-rearm stays on
> schedule_work(&ht->run_work).
> 
>  include/linux/rhashtable-types.h |  3 +++
>  include/linux/rhashtable.h       |  3 ++-
>  lib/rhashtable.c                 | 31 ++++++++++++++++++++++++++++---
>  3 files changed, 33 insertions(+), 4 deletions(-)

Acked-by: Herbert Xu <herbert@gondor.apana.org.au>

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

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

* Re: [PATCH v3] rhashtable: Bounce deferred worker kick through irq_work
  2026-04-21  6:06     ` Herbert Xu
@ 2026-04-21  6:14       ` Tejun Heo
  0 siblings, 0 replies; 12+ messages in thread
From: Tejun Heo @ 2026-04-21  6:14 UTC (permalink / raw)
  To: Herbert Xu; +Cc: Thomas Graf, Andrew Morton, linux-crypto, linux-kernel

Hello,

Applied to sched_ext/for-7.1-fixes.

Thanks.
--
tejun

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

* Re: [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set
  2026-04-19 18:19 [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set Tejun Heo
  2026-04-20  8:44 ` Herbert Xu
  2026-04-20 18:12 ` [PATCH v2] rhashtable: Bounce deferred worker kick through irq_work Tejun Heo
@ 2026-04-27 23:12 ` kernel test robot
  2026-04-28  7:44 ` kernel test robot
  2026-05-07  8:56 ` kernel test robot
  4 siblings, 0 replies; 12+ messages in thread
From: kernel test robot @ 2026-04-27 23:12 UTC (permalink / raw)
  To: Tejun Heo; +Cc: llvm, oe-kbuild-all

Hi Tejun,

[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:

[auto build test ERROR on v7.0]
[also build test ERROR on linus/master]
[cannot apply to tj-sched-ext/for-7.1-fixes next-20260427]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Tejun-Heo/rhashtable-Bounce-deferred-worker-kick-through-irq_work-when-insecure_elasticity-is-set/20260426-103416
base:   v7.0
patch link:    https://lore.kernel.org/r/67fedbf2-914b-44f7-9422-1fe97d833705%40kernel.org
patch subject: [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set
config: s390-allmodconfig (https://download.01.org/0day-ci/archive/20260428/202604280709.2xKuz7sZ-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260428/202604280709.2xKuz7sZ-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/202604280709.2xKuz7sZ-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from lib/rhashtable.c:25:
>> include/linux/rhashtable.h:768:12: error: no member named 'insecure_elasticity' in 'struct rhashtable_params'
     768 |         if (ht->p.insecure_elasticity)
         |             ~~~~~ ^
>> lib/rhashtable.c:1095:12: error: no member named 'insecure_elasticity' in 'struct rhashtable_params'
    1095 |         if (ht->p.insecure_elasticity)
         |             ~~~~~ ^
   lib/rhashtable.c:1162:12: error: no member named 'insecure_elasticity' in 'struct rhashtable_params'
    1162 |         if (ht->p.insecure_elasticity)
         |             ~~~~~ ^
   3 errors generated.
--
   In file included from lib/test_rhashtable.c:20:
>> include/linux/rhashtable.h:768:12: error: no member named 'insecure_elasticity' in 'struct rhashtable_params'
     768 |         if (ht->p.insecure_elasticity)
         |             ~~~~~ ^
   1 error generated.
--
   In file included from drivers/net/ethernet/intel/igc/igc_main.c:12:
   In file included from include/linux/bpf_trace.h:5:
   In file included from include/trace/events/xdp.h:288:
   In file included from include/net/xdp_priv.h:5:
>> include/linux/rhashtable.h:768:12: error: no member named 'insecure_elasticity' in 'struct rhashtable_params'
     768 |         if (ht->p.insecure_elasticity)
         |             ~~~~~ ^
   drivers/net/ethernet/intel/igc/igc_main.c:1264:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1264 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_VLAN,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1265 |                                  IGC_ADVTXD_DCMD_VLE);
         |                                  ~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1268:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1268 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSO,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1269 |                                  (IGC_ADVTXD_DCMD_TSE));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1274:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1274 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1275 |                                  (IGC_ADVTXD_MAC_TSTAMP));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1277:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1277 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_1,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1278 |                                  (IGC_ADVTXD_TSTAMP_REG_1));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1280:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1280 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_2,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1281 |                                  (IGC_ADVTXD_TSTAMP_REG_2));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1283:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1283 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_3,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1284 |                                  (IGC_ADVTXD_TSTAMP_REG_3));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1287:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1287 |         cmd_type ^= IGC_SET_FLAG(skb->no_fcs, 1, IGC_ADVTXD_DCMD_IFCS);
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1299:19: warning: division by zero is undefined [-Wdivision-by-zero]
    1299 |         olinfo_status |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_CSUM,
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1300 |                                       (IGC_TXD_POPTS_TXSM << 8));
         |                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1303:19: warning: division by zero is undefined [-Wdivision-by-zero]
    1303 |         olinfo_status |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_IPV4,
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1304 |                                       (IGC_TXD_POPTS_IXSM << 8));
         |                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:2971:25: warning: division by zero is undefined [-Wdivision-by-zero]
    2971 |                 meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
         |                                       ^~~~~~~~~~~~~~~~~~~~~~
    2972 |                                                    IGC_TX_FLAGS_TSTAMP,
         |                                                    ~~~~~~~~~~~~~~~~~~~~
    2973 |                                                    (IGC_ADVTXD_MAC_TSTAMP));
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:2974:25: warning: division by zero is undefined [-Wdivision-by-zero]
    2974 |                 meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
         |                                       ^~~~~~~~~~~~~~~~~~~~~~
    2975 |                                                    IGC_TX_FLAGS_TSTAMP_1,
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~
    2976 |                                                    (IGC_ADVTXD_TSTAMP_REG_1));
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:2977:25: warning: division by zero is undefined [-Wdivision-by-zero]
    2977 |                 meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
         |                                       ^~~~~~~~~~~~~~~~~~~~~~
    2978 |                                                    IGC_TX_FLAGS_TSTAMP_2,
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~
    2979 |                                                    (IGC_ADVTXD_TSTAMP_REG_2));
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/igc/igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
--
   In file included from igc_main.c:12:
   In file included from include/linux/bpf_trace.h:5:
   In file included from include/trace/events/xdp.h:288:
   In file included from include/net/xdp_priv.h:5:
>> include/linux/rhashtable.h:768:12: error: no member named 'insecure_elasticity' in 'struct rhashtable_params'
     768 |         if (ht->p.insecure_elasticity)
         |             ~~~~~ ^
   igc_main.c:1264:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1264 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_VLAN,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1265 |                                  IGC_ADVTXD_DCMD_VLE);
         |                                  ~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1268:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1268 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSO,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1269 |                                  (IGC_ADVTXD_DCMD_TSE));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1274:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1274 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1275 |                                  (IGC_ADVTXD_MAC_TSTAMP));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1277:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1277 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_1,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1278 |                                  (IGC_ADVTXD_TSTAMP_REG_1));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1280:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1280 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_2,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1281 |                                  (IGC_ADVTXD_TSTAMP_REG_2));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1283:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1283 |         cmd_type |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_TSTAMP_3,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1284 |                                  (IGC_ADVTXD_TSTAMP_REG_3));
         |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1287:14: warning: division by zero is undefined [-Wdivision-by-zero]
    1287 |         cmd_type ^= IGC_SET_FLAG(skb->no_fcs, 1, IGC_ADVTXD_DCMD_IFCS);
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1299:19: warning: division by zero is undefined [-Wdivision-by-zero]
    1299 |         olinfo_status |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_CSUM,
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1300 |                                       (IGC_TXD_POPTS_TXSM << 8));
         |                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1303:19: warning: division by zero is undefined [-Wdivision-by-zero]
    1303 |         olinfo_status |= IGC_SET_FLAG(tx_flags, IGC_TX_FLAGS_IPV4,
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1304 |                                       (IGC_TXD_POPTS_IXSM << 8));
         |                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:2971:25: warning: division by zero is undefined [-Wdivision-by-zero]
    2971 |                 meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
         |                                       ^~~~~~~~~~~~~~~~~~~~~~
    2972 |                                                    IGC_TX_FLAGS_TSTAMP,
         |                                                    ~~~~~~~~~~~~~~~~~~~~
    2973 |                                                    (IGC_ADVTXD_MAC_TSTAMP));
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:2974:25: warning: division by zero is undefined [-Wdivision-by-zero]
    2974 |                 meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
         |                                       ^~~~~~~~~~~~~~~~~~~~~~
    2975 |                                                    IGC_TX_FLAGS_TSTAMP_1,
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~
    2976 |                                                    (IGC_ADVTXD_TSTAMP_REG_1));
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'
    1254 |          ((u32)((_input) & (_flag)) / ((_flag) / (_result))))
         |                                     ^ ~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:2977:25: warning: division by zero is undefined [-Wdivision-by-zero]
    2977 |                 meta_req->cmd_type |= IGC_SET_FLAG(tx_flags,
         |                                       ^~~~~~~~~~~~~~~~~~~~~~
    2978 |                                                    IGC_TX_FLAGS_TSTAMP_2,
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~
    2979 |                                                    (IGC_ADVTXD_TSTAMP_REG_2));
         |                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~
   igc_main.c:1254:30: note: expanded from macro 'IGC_SET_FLAG'


vim +768 include/linux/rhashtable.h

   757	
   758	/*
   759	 * Kick the deferred rehash worker. With insecure_elasticity the caller may
   760	 * hold a raw spinlock. schedule_work() under a raw spinlock records
   761	 * caller_lock -> pool->lock -> pi_lock -> rq->__lock. If any of these
   762	 * locks is acquired in the reverse direction elsewhere, the cycle closes.
   763	 * Bounce through irq_work so schedule_work() runs from hard IRQ context
   764	 * with the caller's lock no longer held.
   765	 */
   766	static void rhashtable_kick_deferred_worker(struct rhashtable *ht)
   767	{
 > 768		if (ht->p.insecure_elasticity)
   769			irq_work_queue(&ht->run_irq_work);
   770		else
   771			schedule_work(&ht->run_work);
   772	}
   773	

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

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

* Re: [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set
  2026-04-19 18:19 [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set Tejun Heo
                   ` (2 preceding siblings ...)
  2026-04-27 23:12 ` [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set kernel test robot
@ 2026-04-28  7:44 ` kernel test robot
  2026-05-07  8:56 ` kernel test robot
  4 siblings, 0 replies; 12+ messages in thread
From: kernel test robot @ 2026-04-28  7:44 UTC (permalink / raw)
  To: Tejun Heo; +Cc: oe-kbuild-all

Hi Tejun,

[This is a private test report for your RFC patch.]
kernel test robot noticed the following build errors:

[auto build test ERROR on v7.0]
[also build test ERROR on linus/master]
[cannot apply to tj-sched-ext/for-7.1-fixes next-20260427]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Tejun-Heo/rhashtable-Bounce-deferred-worker-kick-through-irq_work-when-insecure_elasticity-is-set/20260426-103416
base:   v7.0
patch link:    https://lore.kernel.org/r/67fedbf2-914b-44f7-9422-1fe97d833705%40kernel.org
patch subject: [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set
config: sh-allyesconfig (https://download.01.org/0day-ci/archive/20260428/202604281553.zt7WUfFH-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260428/202604281553.zt7WUfFH-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/202604281553.zt7WUfFH-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from lib/rhashtable.c:25:
   include/linux/rhashtable.h: In function 'rhashtable_kick_deferred_worker':
>> include/linux/rhashtable.h:768:18: error: 'struct rhashtable_params' has no member named 'insecure_elasticity'
     768 |         if (ht->p.insecure_elasticity)
         |                  ^
   lib/rhashtable.c: In function 'rhashtable_init_noprof':
>> lib/rhashtable.c:1095:18: error: 'struct rhashtable_params' has no member named 'insecure_elasticity'
    1095 |         if (ht->p.insecure_elasticity)
         |                  ^
   lib/rhashtable.c: In function 'rhashtable_free_and_destroy':
   lib/rhashtable.c:1162:18: error: 'struct rhashtable_params' has no member named 'insecure_elasticity'
    1162 |         if (ht->p.insecure_elasticity)
         |                  ^
--
   In file included from lib/test_rhashtable.c:20:
   include/linux/rhashtable.h: In function 'rhashtable_kick_deferred_worker':
>> include/linux/rhashtable.h:768:18: error: 'struct rhashtable_params' has no member named 'insecure_elasticity'
     768 |         if (ht->p.insecure_elasticity)
         |                  ^


vim +768 include/linux/rhashtable.h

   757	
   758	/*
   759	 * Kick the deferred rehash worker. With insecure_elasticity the caller may
   760	 * hold a raw spinlock. schedule_work() under a raw spinlock records
   761	 * caller_lock -> pool->lock -> pi_lock -> rq->__lock. If any of these
   762	 * locks is acquired in the reverse direction elsewhere, the cycle closes.
   763	 * Bounce through irq_work so schedule_work() runs from hard IRQ context
   764	 * with the caller's lock no longer held.
   765	 */
   766	static void rhashtable_kick_deferred_worker(struct rhashtable *ht)
   767	{
 > 768		if (ht->p.insecure_elasticity)
   769			irq_work_queue(&ht->run_irq_work);
   770		else
   771			schedule_work(&ht->run_work);
   772	}
   773	

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

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

* Re: [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set
  2026-04-19 18:19 [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set Tejun Heo
                   ` (3 preceding siblings ...)
  2026-04-28  7:44 ` kernel test robot
@ 2026-05-07  8:56 ` kernel test robot
  4 siblings, 0 replies; 12+ messages in thread
From: kernel test robot @ 2026-05-07  8:56 UTC (permalink / raw)
  To: Tejun Heo; +Cc: llvm, oe-kbuild-all

Hi Tejun,

[This is a private test report for your RFC patch.]
kernel test robot noticed the following build warnings:

[auto build test WARNING on v7.0]
[cannot apply to tj-sched-ext/for-7.1-fixes linus/master next-20260506]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Tejun-Heo/rhashtable-Bounce-deferred-worker-kick-through-irq_work-when-insecure_elasticity-is-set/20260426-103416
base:   v7.0
patch link:    https://lore.kernel.org/r/67fedbf2-914b-44f7-9422-1fe97d833705%40kernel.org
patch subject: [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set
config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20260507/202605071043.7pOYYoAU-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
rustc: rustc 1.88.0 (6b00bc388 2025-06-23)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260507/202605071043.7pOYYoAU-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/202605071043.7pOYYoAU-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from ipc/msg.c:41:
   include/linux/rhashtable.h:768:12: error: no member named 'insecure_elasticity' in 'struct rhashtable_params'
     768 |         if (ht->p.insecure_elasticity)
         |             ~~~~~ ^
>> ipc/msg.c:497:20: warning: implicit conversion from 'int' to 'unsigned short' changes value from 32768000 to 0 [-Wconstant-conversion]
     497 |         msginfo->msgseg = MSGSEG;
         |                         ~ ^~~~~~
   include/uapi/linux/msg.h:87:38: note: expanded from macro 'MSGSEG'
      87 | #define MSGSEG (__MSGSEG <= 0xffff ? __MSGSEG : 0xffff)
         |                                      ^~~~~~~~
   include/uapi/linux/msg.h:86:36: note: expanded from macro '__MSGSEG'
      86 | #define __MSGSEG ((MSGPOOL * 1024) / MSGSSZ) /* max no. of segments */
         |                   ~~~~~~~~~~~~~~~~~^~~~~~~~
   1 warning and 1 error generated.
--
   In file included from drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:29:
   In file included from include/linux/bpf_trace.h:5:
   In file included from include/trace/events/xdp.h:288:
   In file included from include/net/xdp_priv.h:5:
   include/linux/rhashtable.h:768:12: error: no member named 'insecure_elasticity' in 'struct rhashtable_params'
     768 |         if (ht->p.insecure_elasticity)
         |             ~~~~~ ^
>> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8878:14: warning: division by zero is undefined [-Wdivision-by-zero]
    8878 |         cmd_type |= IXGBE_SET_FLAG(tx_flags, IXGBE_TX_FLAGS_HW_VLAN,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    8879 |                                    IXGBE_ADVTXD_DCMD_VLE);
         |                                    ~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8868:26: note: expanded from macro 'IXGBE_SET_FLAG'
    8868 |          ((u32)(_input & _flag) / (_flag / _result)))
         |                                 ^ ~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8882:14: warning: division by zero is undefined [-Wdivision-by-zero]
    8882 |         cmd_type |= IXGBE_SET_FLAG(tx_flags, IXGBE_TX_FLAGS_TSO,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    8883 |                                    IXGBE_ADVTXD_DCMD_TSE);
         |                                    ~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8868:26: note: expanded from macro 'IXGBE_SET_FLAG'
    8868 |          ((u32)(_input & _flag) / (_flag / _result)))
         |                                 ^ ~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8886:14: warning: division by zero is undefined [-Wdivision-by-zero]
    8886 |         cmd_type |= IXGBE_SET_FLAG(tx_flags, IXGBE_TX_FLAGS_TSTAMP,
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    8887 |                                    IXGBE_ADVTXD_MAC_TSTAMP);
         |                                    ~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8868:26: note: expanded from macro 'IXGBE_SET_FLAG'
    8868 |          ((u32)(_input & _flag) / (_flag / _result)))
         |                                 ^ ~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8890:14: warning: division by zero is undefined [-Wdivision-by-zero]
    8890 |         cmd_type ^= IXGBE_SET_FLAG(skb->no_fcs, 1, IXGBE_ADVTXD_DCMD_IFCS);
         |                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8868:26: note: expanded from macro 'IXGBE_SET_FLAG'
    8868 |          ((u32)(_input & _flag) / (_flag / _result)))
         |                                 ^ ~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8901:19: warning: division by zero is undefined [-Wdivision-by-zero]
    8901 |         olinfo_status |= IXGBE_SET_FLAG(tx_flags,
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~
    8902 |                                         IXGBE_TX_FLAGS_CSUM,
         |                                         ~~~~~~~~~~~~~~~~~~~~
    8903 |                                         IXGBE_ADVTXD_POPTS_TXSM);
         |                                         ~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8868:26: note: expanded from macro 'IXGBE_SET_FLAG'
    8868 |          ((u32)(_input & _flag) / (_flag / _result)))
         |                                 ^ ~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8906:19: warning: division by zero is undefined [-Wdivision-by-zero]
    8906 |         olinfo_status |= IXGBE_SET_FLAG(tx_flags,
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~
    8907 |                                         IXGBE_TX_FLAGS_IPV4,
         |                                         ~~~~~~~~~~~~~~~~~~~~
    8908 |                                         IXGBE_ADVTXD_POPTS_IXSM);
         |                                         ~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8868:26: note: expanded from macro 'IXGBE_SET_FLAG'
    8868 |          ((u32)(_input & _flag) / (_flag / _result)))
         |                                 ^ ~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8911:19: warning: division by zero is undefined [-Wdivision-by-zero]
    8911 |         olinfo_status |= IXGBE_SET_FLAG(tx_flags,
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~
    8912 |                                         IXGBE_TX_FLAGS_IPSEC,
         |                                         ~~~~~~~~~~~~~~~~~~~~~
    8913 |                                         IXGBE_ADVTXD_POPTS_IPSEC);
         |                                         ~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8868:26: note: expanded from macro 'IXGBE_SET_FLAG'
    8868 |          ((u32)(_input & _flag) / (_flag / _result)))
         |                                 ^ ~~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8919:19: warning: division by zero is undefined [-Wdivision-by-zero]
    8919 |         olinfo_status |= IXGBE_SET_FLAG(tx_flags,
         |                          ^~~~~~~~~~~~~~~~~~~~~~~~
    8920 |                                         IXGBE_TX_FLAGS_CC,
         |                                         ~~~~~~~~~~~~~~~~~~
    8921 |                                         IXGBE_ADVTXD_CC);
         |                                         ~~~~~~~~~~~~~~~~
   drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:8868:26: note: expanded from macro 'IXGBE_SET_FLAG'
    8868 |          ((u32)(_input & _flag) / (_flag / _result)))
         |                                 ^ ~~~~~~~~~~~~~~~~~
   8 warnings and 1 error generated.


vim +497 ipc/msg.c

a0d092fc2df845 Pierre Peiffer  2008-04-29  476  
156d9ed1260ee5 Al Viro         2017-07-09  477  static int msgctl_info(struct ipc_namespace *ns, int msqid,
156d9ed1260ee5 Al Viro         2017-07-09  478  			 int cmd, struct msginfo *msginfo)
a0d092fc2df845 Pierre Peiffer  2008-04-29  479  {
2cafed30f150f7 Davidlohr Bueso 2013-07-08  480  	int err;
27c331a1746142 Manfred Spraul  2018-08-21  481  	int max_idx;
5a06a363ef4844 Ingo Molnar     2006-07-30  482  
5a06a363ef4844 Ingo Molnar     2006-07-30  483  	/*
5a06a363ef4844 Ingo Molnar     2006-07-30  484  	 * We must not return kernel stack data.
^1da177e4c3f41 Linus Torvalds  2005-04-16  485  	 * due to padding, it's not enough
^1da177e4c3f41 Linus Torvalds  2005-04-16  486  	 * to set all member fields.
^1da177e4c3f41 Linus Torvalds  2005-04-16  487  	 */
^1da177e4c3f41 Linus Torvalds  2005-04-16  488  	err = security_msg_queue_msgctl(NULL, cmd);
^1da177e4c3f41 Linus Torvalds  2005-04-16  489  	if (err)
^1da177e4c3f41 Linus Torvalds  2005-04-16  490  		return err;
^1da177e4c3f41 Linus Torvalds  2005-04-16  491  
156d9ed1260ee5 Al Viro         2017-07-09  492  	memset(msginfo, 0, sizeof(*msginfo));
156d9ed1260ee5 Al Viro         2017-07-09  493  	msginfo->msgmni = ns->msg_ctlmni;
156d9ed1260ee5 Al Viro         2017-07-09  494  	msginfo->msgmax = ns->msg_ctlmax;
156d9ed1260ee5 Al Viro         2017-07-09  495  	msginfo->msgmnb = ns->msg_ctlmnb;
156d9ed1260ee5 Al Viro         2017-07-09  496  	msginfo->msgssz = MSGSSZ;
156d9ed1260ee5 Al Viro         2017-07-09 @497  	msginfo->msgseg = MSGSEG;
d9a605e40b1376 Davidlohr Bueso 2013-09-11  498  	down_read(&msg_ids(ns).rwsem);
72d1e611082eda Jiebin Sun      2022-09-14  499  	if (cmd == MSG_INFO)
156d9ed1260ee5 Al Viro         2017-07-09  500  		msginfo->msgpool = msg_ids(ns).in_use;
72d1e611082eda Jiebin Sun      2022-09-14  501  	max_idx = ipc_get_maxidx(&msg_ids(ns));
72d1e611082eda Jiebin Sun      2022-09-14  502  	up_read(&msg_ids(ns).rwsem);
72d1e611082eda Jiebin Sun      2022-09-14  503  	if (cmd == MSG_INFO) {
72d1e611082eda Jiebin Sun      2022-09-14  504  		msginfo->msgmap = min_t(int,
72d1e611082eda Jiebin Sun      2022-09-14  505  				     percpu_counter_sum(&ns->percpu_msg_hdrs),
72d1e611082eda Jiebin Sun      2022-09-14  506  				     INT_MAX);
72d1e611082eda Jiebin Sun      2022-09-14  507  		msginfo->msgtql = min_t(int,
72d1e611082eda Jiebin Sun      2022-09-14  508  		                     percpu_counter_sum(&ns->percpu_msg_bytes),
72d1e611082eda Jiebin Sun      2022-09-14  509  				     INT_MAX);
^1da177e4c3f41 Linus Torvalds  2005-04-16  510  	} else {
156d9ed1260ee5 Al Viro         2017-07-09  511  		msginfo->msgmap = MSGMAP;
156d9ed1260ee5 Al Viro         2017-07-09  512  		msginfo->msgpool = MSGPOOL;
156d9ed1260ee5 Al Viro         2017-07-09  513  		msginfo->msgtql = MSGTQL;
^1da177e4c3f41 Linus Torvalds  2005-04-16  514  	}
27c331a1746142 Manfred Spraul  2018-08-21  515  	return (max_idx < 0) ? 0 : max_idx;
^1da177e4c3f41 Linus Torvalds  2005-04-16  516  }
2cafed30f150f7 Davidlohr Bueso 2013-07-08  517  

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

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

* Re: [PATCH v3] rhashtable: Bounce deferred worker kick through irq_work
  2026-04-21  6:03   ` [PATCH v3] " Tejun Heo
  2026-04-21  6:06     ` Herbert Xu
@ 2026-05-12  6:07     ` Hillf Danton
  1 sibling, 0 replies; 12+ messages in thread
From: Hillf Danton @ 2026-05-12  6:07 UTC (permalink / raw)
  To: Tejun Heo
  Cc: Herbert Xu, Thomas Graf, Andrew Morton, linux-crypto,
	linux-kernel

On Mon, 20 Apr 2026 20:03:26 -1000 Tejun Heo wrote:
> --- a/lib/rhashtable.c
> +++ b/lib/rhashtable.c
> @@ -441,10 +441,33 @@ static void rht_deferred_worker(struct work_struct *work)
>  
>  	mutex_unlock(&ht->mutex);
>  
> +	/*
> +	 * Re-arm via @run_work, not @run_irq_work.
> +	 * rhashtable_free_and_destroy() drains async work as irq_work_sync()
> +	 * followed by cancel_work_sync(). If this site queued irq_work while
> +	 * cancel_work_sync() was waiting for us, irq_work_sync() would already
> +	 * have returned and the stale irq_work could fire post-teardown.
> +	 * cancel_work_sync() natively handles self-requeue on @run_work.
> +	 */
>  	if (err)
>  		schedule_work(&ht->run_work);
>  }
> 
Two cents: add BUG to capture the failure of handling self-requeue.

--- x/kernel/workqueue.c
+++ y/kernel/workqueue.c
@@ -2369,6 +2369,10 @@ retry:
 		work_flags |= WORK_STRUCT_INACTIVE;
 		insert_work(pwq, work, &pwq->inactive_works, work_flags);
 	}
+	do {
+		unsigned long data = *work_data_bits(work);
+		BUG_ON(data & WORK_OFFQ_DISABLE_MASK);
+	} while (0);
 
 out:
 	raw_spin_unlock(&pool->lock);
--

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

end of thread, other threads:[~2026-05-12  6:07 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-19 18:19 [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set Tejun Heo
2026-04-20  8:44 ` Herbert Xu
2026-04-20 17:02   ` Tejun Heo
2026-04-20 18:12 ` [PATCH v2] rhashtable: Bounce deferred worker kick through irq_work Tejun Heo
2026-04-21  3:02   ` Herbert Xu
2026-04-21  6:03   ` [PATCH v3] " Tejun Heo
2026-04-21  6:06     ` Herbert Xu
2026-04-21  6:14       ` Tejun Heo
2026-05-12  6:07     ` Hillf Danton
2026-04-27 23:12 ` [RFC PATCH] rhashtable: Bounce deferred worker kick through irq_work when insecure_elasticity is set kernel test robot
2026-04-28  7:44 ` kernel test robot
2026-05-07  8:56 ` kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.