diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2011-06-14 19:02:29 -0400 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2011-07-07 22:26:27 -0400 |
| commit | e4a3f541f0b67fdad98b326c851dfe7f4b6b6dad (patch) | |
| tree | e93b858ab3313374d23c4ebadc5077816f1894f2 /kernel/trace | |
| parent | e08fbb78f03fe2c4f88824faf6f51ce6af185e11 (diff) | |
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>
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/trace.h | 50 | ||||
| -rw-r--r-- | kernel/trace/trace_functions_graph.c | 2 |
2 files changed, 35 insertions, 17 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index a3e2db708072..651f35be372a 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
| @@ -278,6 +278,29 @@ struct tracer { | |||
| 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 | #define TRACE_PIPE_ALL_CPU -1 | 304 | #define TRACE_PIPE_ALL_CPU -1 |
| 282 | 305 | ||
| 283 | int tracer_init(struct tracer *t, struct trace_array *tr); | 306 | int tracer_init(struct tracer *t, struct trace_array *tr); |
| @@ -516,8 +539,18 @@ static inline int ftrace_graph_addr(unsigned long addr) | |||
| 516 | return 1; | 539 | return 1; |
| 517 | 540 | ||
| 518 | for (i = 0; i < ftrace_graph_count; i++) { | 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 | return 1; | 552 | return 1; |
| 553 | } | ||
| 521 | } | 554 | } |
| 522 | 555 | ||
| 523 | return 0; | 556 | return 0; |
| @@ -794,19 +827,4 @@ extern const char *__stop___trace_bprintk_fmt[]; | |||
| 794 | FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print)) | 827 | FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print)) |
| 795 | #include "trace_entries.h" | 828 | #include "trace_entries.h" |
| 796 | 829 | ||
| 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 | |||
| 812 | #endif /* _LINUX_KERNEL_TRACE_H */ | 830 | #endif /* _LINUX_KERNEL_TRACE_H */ |
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index e8d6bb55d719..a7d2a4c653d8 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
| @@ -227,7 +227,7 @@ int __trace_graph_entry(struct trace_array *tr, | |||
| 227 | 227 | ||
| 228 | static inline int ftrace_graph_ignore_irqs(void) | 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 | return 0; | 231 | return 0; |
| 232 | 232 | ||
| 233 | return in_irq(); | 233 | return in_irq(); |
