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(); |