diff options
| author | Steven Rostedt (VMware) <rostedt@goodmis.org> | 2017-05-12 13:15:45 -0400 |
|---|---|---|
| committer | Steven Rostedt (VMware) <rostedt@goodmis.org> | 2017-05-18 23:57:56 -0400 |
| commit | a33d7d94eed92b23fbbc7b0de06a41b2bbaa49e3 (patch) | |
| tree | 4663e28c01cc8cffb139af6afeb950532d1e4adc /kernel | |
| parent | 545a028190dae4437aac4f86da7c8ab20857647c (diff) | |
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/20170512172449.879684501@goodmis.org
Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/trace/trace.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index fcc9a2d774c3..1122f151466f 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, | |||
| 2568 | void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, | 2568 | void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, |
| 2569 | int pc) | 2569 | int pc) |
| 2570 | { | 2570 | { |
| 2571 | __ftrace_trace_stack(tr->trace_buffer.buffer, flags, skip, pc, NULL); | 2571 | struct ring_buffer *buffer = tr->trace_buffer.buffer; |
| 2572 | |||
| 2573 | if (rcu_is_watching()) { | ||
| 2574 | __ftrace_trace_stack(buffer, flags, skip, pc, NULL); | ||
| 2575 | return; | ||
| 2576 | } | ||
| 2577 | |||
| 2578 | /* | ||
| 2579 | * When an NMI triggers, RCU is enabled via rcu_nmi_enter(), | ||
| 2580 | * but if the above rcu_is_watching() failed, then the NMI | ||
| 2581 | * triggered someplace critical, and rcu_irq_enter() should | ||
| 2582 | * not be called from NMI. | ||
| 2583 | */ | ||
| 2584 | if (unlikely(in_nmi())) | ||
| 2585 | return; | ||
| 2586 | |||
| 2587 | /* | ||
| 2588 | * It is possible that a function is being traced in a | ||
| 2589 | * location that RCU is not watching. A call to | ||
| 2590 | * rcu_irq_enter() will make sure that it is, but there's | ||
| 2591 | * a few internal rcu functions that could be traced | ||
| 2592 | * where that wont work either. In those cases, we just | ||
| 2593 | * do nothing. | ||
| 2594 | */ | ||
| 2595 | if (unlikely(rcu_irq_enter_disabled())) | ||
| 2596 | return; | ||
| 2597 | |||
| 2598 | rcu_irq_enter_irqson(); | ||
| 2599 | __ftrace_trace_stack(buffer, flags, skip, pc, NULL); | ||
| 2600 | rcu_irq_exit_irqson(); | ||
| 2572 | } | 2601 | } |
| 2573 | 2602 | ||
| 2574 | /** | 2603 | /** |
