aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-06-14 19:02:29 -0400
committerSteven Rostedt <rostedt@goodmis.org>2011-07-07 22:26:27 -0400
commite4a3f541f0b67fdad98b326c851dfe7f4b6b6dad (patch)
treee93b858ab3313374d23c4ebadc5077816f1894f2 /kernel/trace
parente08fbb78f03fe2c4f88824faf6f51ce6af185e11 (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.h50
-rw-r--r--kernel/trace/trace_functions_graph.c2
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
283int tracer_init(struct tracer *t, struct trace_array *tr); 306int 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
228static inline int ftrace_graph_ignore_irqs(void) 228static 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();