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;
