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


Reply via email to