From: Masami Hiramatsu (Google) <[email protected]>

Currently rhashtable always uses call_rcu() to free old bucket tables
upon table resizing. However, some callers (such as fprobe) operate
under preempt_disable() without holding rcu_read_lock(), relying on
Tasks Rude RCU grace periods instead of standard RCU.

Add a use_tasks_rude boolean flag to struct rhashtable_params. When
enabled, rhashtable_rehash_table() frees old bucket tables using
call_rcu_tasks_rude() instead of call_rcu(). Existing callers continue
to default to call_rcu().

Assisted-by: LLM
Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
---
 include/linux/rhashtable-types.h |    2 ++
 lib/rhashtable.c                 |    5 ++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/linux/rhashtable-types.h b/include/linux/rhashtable-types.h
index 57c11ec9dc64..24282ae68409 100644
--- a/include/linux/rhashtable-types.h
+++ b/include/linux/rhashtable-types.h
@@ -52,6 +52,7 @@ typedef int (*rht_obj_cmpfn_t)(struct rhashtable_compare_arg 
*arg,
  * @min_size: Minimum size while shrinking
  * @insecure_elasticity: Set to true to disable chain length checks
  * @automatic_shrinking: Enable automatic shrinking of tables
+ * @use_tasks_rude: Use call_rcu_tasks_rude() to free bucket tables
  * @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
@@ -65,6 +66,7 @@ struct rhashtable_params {
        u16                     min_size;
        bool                    insecure_elasticity;
        bool                    automatic_shrinking;
+       bool                    use_tasks_rude;
        rht_hashfn_t            hashfn;
        rht_obj_hashfn_t        obj_hashfn;
        rht_obj_cmpfn_t         obj_cmpfn;
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 6362896e4f09..b183fb112a70 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -359,7 +359,10 @@ static int rhashtable_rehash_table(struct rhashtable *ht)
         * rhashtable_walk_stop() can use rcu_head_after_call_rcu()
         * to check if it should not re-link the table.
         */
-       call_rcu(&old_tbl->rcu, bucket_table_free_rcu);
+       if (ht->p.use_tasks_rude)
+               call_rcu_tasks_rude(&old_tbl->rcu, bucket_table_free_rcu);
+       else
+               call_rcu(&old_tbl->rcu, bucket_table_free_rcu);
        spin_unlock(&ht->lock);
 
        return rht_dereference(new_tbl->future_tbl, ht) ? -EAGAIN : 0;


Reply via email to