Commit e4a3f541f0b67fdad98b326c851dfe7f4b6b6dad

Authored by Steven Rostedt
Committed by Steven Rostedt
1 parent e08fbb78f0

tracing: Still trace filtered irq functions when irq trace is disabled

If a function is set to be traced by the set_graph_function, but the
option funcgraph-irqs is zero, and the traced function happens to be
called from a interrupt, it will not be traced.

The point of funcgraph-irqs is to not trace interrupts when we are
preempted by an irq, not to not trace functions we want to trace that
happen to be *in* a irq.

Luckily the current->trace_recursion element is perfect to add a flag
to help us be able to trace functions within an interrupt even when
we are not tracing interrupts that preempt the trace.

Reported-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Tested-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

Showing 2 changed files with 35 additions and 17 deletions Side-by-side Diff

kernel/trace/trace.h
... ... @@ -278,6 +278,29 @@
278 278 };
279 279  
280 280  
  281 +/* Only current can touch trace_recursion */
  282 +#define trace_recursion_inc() do { (current)->trace_recursion++; } while (0)
  283 +#define trace_recursion_dec() do { (current)->trace_recursion--; } while (0)
  284 +
  285 +/* Ring buffer has the 10 LSB bits to count */
  286 +#define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff)
  287 +
  288 +/* for function tracing recursion */
  289 +#define TRACE_INTERNAL_BIT (1<<11)
  290 +#define TRACE_GLOBAL_BIT (1<<12)
  291 +/*
  292 + * Abuse of the trace_recursion.
  293 + * As we need a way to maintain state if we are tracing the function
  294 + * graph in irq because we want to trace a particular function that
  295 + * was called in irq context but we have irq tracing off. Since this
  296 + * can only be modified by current, we can reuse trace_recursion.
  297 + */
  298 +#define TRACE_IRQ_BIT (1<<13)
  299 +
  300 +#define trace_recursion_set(bit) do { (current)->trace_recursion |= (bit); } while (0)
  301 +#define trace_recursion_clear(bit) do { (current)->trace_recursion &= ~(bit); } while (0)
  302 +#define trace_recursion_test(bit) ((current)->trace_recursion & (bit))
  303 +
281 304 #define TRACE_PIPE_ALL_CPU -1
282 305  
283 306 int tracer_init(struct tracer *t, struct trace_array *tr);
284 307  
... ... @@ -516,8 +539,18 @@
516 539 return 1;
517 540  
518 541 for (i = 0; i < ftrace_graph_count; i++) {
519   - if (addr == ftrace_graph_funcs[i])
  542 + if (addr == ftrace_graph_funcs[i]) {
  543 + /*
  544 + * If no irqs are to be traced, but a set_graph_function
  545 + * is set, and called by an interrupt handler, we still
  546 + * want to trace it.
  547 + */
  548 + if (in_irq())
  549 + trace_recursion_set(TRACE_IRQ_BIT);
  550 + else
  551 + trace_recursion_clear(TRACE_IRQ_BIT);
520 552 return 1;
  553 + }
521 554 }
522 555  
523 556 return 0;
... ... @@ -793,21 +826,6 @@
793 826 #define FTRACE_ENTRY_DUP(call, struct_name, id, tstruct, print) \
794 827 FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print))
795 828 #include "trace_entries.h"
796   -
797   -/* Only current can touch trace_recursion */
798   -#define trace_recursion_inc() do { (current)->trace_recursion++; } while (0)
799   -#define trace_recursion_dec() do { (current)->trace_recursion--; } while (0)
800   -
801   -/* Ring buffer has the 10 LSB bits to count */
802   -#define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff)
803   -
804   -/* for function tracing recursion */
805   -#define TRACE_INTERNAL_BIT (1<<11)
806   -#define TRACE_GLOBAL_BIT (1<<12)
807   -
808   -#define trace_recursion_set(bit) do { (current)->trace_recursion |= (bit); } while (0)
809   -#define trace_recursion_clear(bit) do { (current)->trace_recursion &= ~(bit); } while (0)
810   -#define trace_recursion_test(bit) ((current)->trace_recursion & (bit))
811 829  
812 830 #endif /* _LINUX_KERNEL_TRACE_H */
kernel/trace/trace_functions_graph.c
... ... @@ -227,7 +227,7 @@
227 227  
228 228 static inline int ftrace_graph_ignore_irqs(void)
229 229 {
230   - if (!ftrace_graph_skip_irqs)
  230 + if (!ftrace_graph_skip_irqs || trace_recursion_test(TRACE_IRQ_BIT))
231 231 return 0;
232 232  
233 233 return in_irq();