On Thu, May 18, 2017 at 09:11:40PM -0400, Steven Rostedt wrote: > From 8260b0308d3ee0f836cd5ea4b177efeb52ab151f Mon Sep 17 00:00:00 2001 > From: "Steven Rostedt (VMware)" <[email protected]> > Date: Fri, 12 May 2017 13:15:45 -0400 > Subject: [PATCH] tracing: Make sure RCU is watching before calling a stack > trace > > As stack tracing now requires "rcu watching", force RCU to be watching when > recording a stack trace. > > Link: http://lkml.kernel.org/r/[email protected] > > Cc: "Paul E. McKenney" <[email protected]> > Signed-off-by: Steven Rostedt (VMware) <[email protected]>
Acked-by: Paul E. McKenney <[email protected]> > --- > > Changes since v2: > > Use rcu_is_watching() instead if checking for in_nmi() and irqs > disabled. But now if rcu_is_watching() fails and in_nmi() is true, > bail. > > kernel/trace/trace.c | 31 ++++++++++++++++++++++++++++++- > 1 file changed, 30 insertions(+), 1 deletion(-) > > diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c > index fcc9a2d..1122f15 100644 > --- a/kernel/trace/trace.c > +++ b/kernel/trace/trace.c > @@ -2568,7 +2568,36 @@ static inline void ftrace_trace_stack(struct > trace_array *tr, > void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, > int pc) > { > - __ftrace_trace_stack(tr->trace_buffer.buffer, flags, skip, pc, NULL); > + struct ring_buffer *buffer = tr->trace_buffer.buffer; > + > + if (rcu_is_watching()) { > + __ftrace_trace_stack(buffer, flags, skip, pc, NULL); > + return; > + } > + > + /* > + * When an NMI triggers, RCU is enabled via rcu_nmi_enter(), > + * but if the above rcu_is_watching() failed, then the NMI > + * triggered someplace critical, and rcu_irq_enter() should > + * not be called from NMI. > + */ > + if (unlikely(in_nmi())) > + return; > + > + /* > + * It is possible that a function is being traced in a > + * location that RCU is not watching. A call to > + * rcu_irq_enter() will make sure that it is, but there's > + * a few internal rcu functions that could be traced > + * where that wont work either. In those cases, we just > + * do nothing. > + */ > + if (unlikely(rcu_irq_enter_disabled())) > + return; > + > + rcu_irq_enter_irqson(); > + __ftrace_trace_stack(buffer, flags, skip, pc, NULL); > + rcu_irq_exit_irqson(); > } > > /** > -- > 2.9.3 >

