From: Masami Hiramatsu (Google) <[email protected]> Currently call_rcu_tasks_rude() is static and private to kernel/rcu/tasks.h, while synchronize_rcu_tasks_rude() is exported. Subsystems that execute handlers under preempt_disable() (such as fprobe and BPF kprobe-multi) cannot safely wait on synchronize_rcu_tasks_rude() in atomic or asynchronous contexts without an asynchronous call_rcu_tasks_rude() variant.
Make call_rcu_tasks_rude() non-static, declare it in include/linux/rcupdate.h, and export it via EXPORT_SYMBOL_GPL(). Also provide fallbacks to call_rcu when Tasks Rude RCU is not configured. Assisted-by: LLM Signed-off-by: Masami Hiramatsu (Google) <[email protected]> --- include/linux/rcupdate.h | 6 ++++++ kernel/rcu/tasks.h | 8 +++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 44c07a66edff..dca61b52dc8c 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -198,7 +198,11 @@ void rcu_tasks_torture_stats_print(char *tt, char *tf); # ifdef CONFIG_TASKS_RUDE_RCU void synchronize_rcu_tasks_rude(void); +void call_rcu_tasks_rude(struct rcu_head *rhp, rcu_callback_t func); void rcu_tasks_rude_torture_stats_print(char *tt, char *tf); +# else +# define call_rcu_tasks_rude call_rcu +# define synchronize_rcu_tasks_rude synchronize_rcu # endif #define rcu_note_voluntary_context_switch(t) rcu_tasks_qs(t, false) @@ -210,6 +214,8 @@ void exit_tasks_rcu_finish(void); #define rcu_note_voluntary_context_switch(t) do { } while (0) #define call_rcu_tasks call_rcu #define synchronize_rcu_tasks synchronize_rcu +#define call_rcu_tasks_rude call_rcu +#define synchronize_rcu_tasks_rude synchronize_rcu static inline void exit_tasks_rcu_start(void) { } static inline void exit_tasks_rcu_finish(void) { } #endif /* #else #ifdef CONFIG_TASKS_RCU_GENERIC */ diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h index 627295396cd9..f0b524d5f3f5 100644 --- a/kernel/rcu/tasks.h +++ b/kernel/rcu/tasks.h @@ -1355,7 +1355,7 @@ static void rcu_tasks_rude_wait_gp(struct rcu_tasks *rtp) schedule_on_each_cpu(rcu_tasks_be_rude); } -static void call_rcu_tasks_rude(struct rcu_head *rhp, rcu_callback_t func); +void call_rcu_tasks_rude(struct rcu_head *rhp, rcu_callback_t func); DEFINE_RCU_TASKS(rcu_tasks_rude, rcu_tasks_rude_wait_gp, call_rcu_tasks_rude, "RCU Tasks Rude"); @@ -1376,14 +1376,12 @@ DEFINE_RCU_TASKS(rcu_tasks_rude, rcu_tasks_rude_wait_gp, call_rcu_tasks_rude, * * See the description of call_rcu() for more detailed information on * memory ordering guarantees. - * - * This is no longer exported, and is instead reserved for use by - * synchronize_rcu_tasks_rude(). */ -static void call_rcu_tasks_rude(struct rcu_head *rhp, rcu_callback_t func) +void call_rcu_tasks_rude(struct rcu_head *rhp, rcu_callback_t func) { call_rcu_tasks_generic(rhp, func, &rcu_tasks_rude); } +EXPORT_SYMBOL_GPL(call_rcu_tasks_rude); /** * synchronize_rcu_tasks_rude - wait for a rude rcu-tasks grace period
