From: "Steven Rostedt (Red Hat)" In order to move enabling of trace events to just after mm_init(), the tracepoint enable code can not use call_rcu_sched() because rcu isn't even initialized yet. Since this can only happen before SMP is set up (and even before interrupts are set up), there's no reason to use call_rcu_sched() at this point. Instead, create a variable called tracepoint_rcu_safe that gets enabled via early_initcall() and if that is not set, free the code directly instead of using call_rcu_sched(). This allows us to enable tracepoints early without issues. Cc: Mathieu Desnoyers Cc: Paul E. McKenney Cc: Thomas Gleixner Signed-off-by: Steven Rostedt --- kernel/tracepoint.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index 3490407dc7b7..9b90ef0ac731 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -33,6 +33,15 @@ extern struct tracepoint * const __stop___tracepoints_ptrs[]; /* Set to 1 to enable tracepoint debug output */ static const int tracepoint_debug; +/* + * traceoint_rcu_is_safe is set to true at early_initcall(). + * Tracepoints can be enabled before rcu is initialized. + * When that happens, there's no reason to free via call_rcu() + * because the system isn't even in SMP mode yet, and rcu isn't + * initialized. Just directly free the old tracepoints instead. + */ +static bool tracepoint_rcu_is_safe; + #ifdef CONFIG_MODULES /* * Tracepoint module list mutex protects the local module list. @@ -76,7 +85,16 @@ static inline void release_probes(struct tracepoint_func *old) if (old) { struct tp_probes *tp_probes = container_of(old, struct tp_probes, probes[0]); - call_rcu_sched(&tp_probes->rcu, rcu_free_old_probes); + /* + * Tracepoints can be enabled before RCU is initialized + * at boot up. If that is the case, do not bother using + * call_rcu() (because that will fail), but instead just + * free directly. + */ + if (likely(tracepoint_rcu_is_safe)) + call_rcu_sched(&tp_probes->rcu, rcu_free_old_probes); + else + rcu_free_old_probes(&tp_probes->rcu); } } @@ -518,3 +536,10 @@ void syscall_unregfunc(void) } } #endif + +static __init int init_tracepoint_rcu(void) +{ + tracepoint_rcu_is_safe = true; + return 0; +} +early_initcall(init_tracepoint_rcu); -- 2.1.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/