[PATCH for-7.1-fixes 1/2] rhashtable: add no_sync_grow option

Tejun Heo
2026-04-17T00:24:51Z

The sync grow path on insert calls get_random_u32() and kvmalloc(), both of
which take regular spinlocks and are unsafe under raw_spinlock_t. Add an
opt-in flag that skips the >100% grow check; inserts always succeed by
appending to the chain, and the deferred worker still grows at >75% load.

sched_ext already uses rhashtable under raw_spinlock_t and is technically
broken, though hard to hit in practice because the tables stay small.

Cc: stable@vger.kernel.org # prerequisite for the next sched_ext fix
Signed-off-by: Tejun Heo <tj@kernel.org>
---
Hello,

The follow-up sched_ext patch is a fix targeting sched_ext/for-7.1-fixes
which I'd like to send Linus's way sooner than later. Would it be okay
to route both patches through sched_ext/for-7.1-fixes? If you'd prefer
to route the rhashtable change differently, that works too. Please let
me know, thanks.

Based on linus/master (3cd8b194bf34).

include/linux/rhashtable-types.h | 2 ++
include/linux/rhashtable.h | 5 ++++-
2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 015c8298bebc..555eea6077f8 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -50,6 +50,7 @@ typedef int (*rht_obj_cmpfn_t)(struct rhashtable_compare_arg *arg,
* @max_size: Maximum size while expanding
* @min_size: Minimum size while shrinking
* @automatic_shrinking: Enable automatic shrinking of tables
+ * @no_sync_grow: Skip sync grow on insert (allows inserts under raw_spinlock_t)
* @hashfn: Hash function (default: jhash2 if !(key_len % 4), or jhash)
* @obj_hashfn: Function to hash object
* @obj_cmpfn: Function to compare key with object
@@ -62,6 +63,7 @@ struct rhashtable_params {
unsigned int max_size;
u16 min_size;
bool automatic_shrinking;
+ bool no_sync_grow;
rht_hashfn_t hashfn;
rht_obj_hashfn_t obj_hashfn;
rht_obj_cmpfn_t obj_cmpfn;
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 0480509a6339..a977a597d288 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -197,11 +197,14 @@ static inline bool rht_shrink_below_30(const struct rhashtable *ht,
* rht_grow_above_100 - returns true if nelems > table-size
* @ht: hash table
* @tbl: current table
+ *
+ * Returns false if the caller opted out of synchronous grow.
*/
static inline bool rht_grow_above_100(const struct rhashtable *ht,
const struct bucket_table *tbl)
{
- return atomic_read(&ht->nelems) > tbl->size &&
+ return !ht->p.no_sync_grow &&
+ atomic_read(&ht->nelems) > tbl->size &&
(!ht->p.max_size || tbl->size < ht->p.max_size);
}

--
2.53.0