Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4a3f541 authored by Steven Rostedt's avatar Steven Rostedt Committed by Steven Rostedt
Browse files

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: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Tested-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent e08fbb78
Loading
Loading
Loading
Loading
+34 −16
Original line number Diff line number Diff line
@@ -278,6 +278,29 @@ struct tracer {
};


/* Only current can touch trace_recursion */
#define trace_recursion_inc() do { (current)->trace_recursion++; } while (0)
#define trace_recursion_dec() do { (current)->trace_recursion--; } while (0)

/* Ring buffer has the 10 LSB bits to count */
#define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff)

/* for function tracing recursion */
#define TRACE_INTERNAL_BIT		(1<<11)
#define TRACE_GLOBAL_BIT		(1<<12)
/*
 * Abuse of the trace_recursion.
 * As we need a way to maintain state if we are tracing the function
 * graph in irq because we want to trace a particular function that
 * was called in irq context but we have irq tracing off. Since this
 * can only be modified by current, we can reuse trace_recursion.
 */
#define TRACE_IRQ_BIT			(1<<13)

#define trace_recursion_set(bit)	do { (current)->trace_recursion |= (bit); } while (0)
#define trace_recursion_clear(bit)	do { (current)->trace_recursion &= ~(bit); } while (0)
#define trace_recursion_test(bit)	((current)->trace_recursion & (bit))

#define TRACE_PIPE_ALL_CPU	-1

int tracer_init(struct tracer *t, struct trace_array *tr);
@@ -516,9 +539,19 @@ static inline int ftrace_graph_addr(unsigned long addr)
		return 1;

	for (i = 0; i < ftrace_graph_count; i++) {
		if (addr == ftrace_graph_funcs[i])
		if (addr == ftrace_graph_funcs[i]) {
			/*
			 * If no irqs are to be traced, but a set_graph_function
			 * is set, and called by an interrupt handler, we still
			 * want to trace it.
			 */
			if (in_irq())
				trace_recursion_set(TRACE_IRQ_BIT);
			else
				trace_recursion_clear(TRACE_IRQ_BIT);
			return 1;
		}
	}

	return 0;
}
@@ -794,19 +827,4 @@ extern const char *__stop___trace_bprintk_fmt[];
	FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print))
#include "trace_entries.h"

/* Only current can touch trace_recursion */
#define trace_recursion_inc() do { (current)->trace_recursion++; } while (0)
#define trace_recursion_dec() do { (current)->trace_recursion--; } while (0)

/* Ring buffer has the 10 LSB bits to count */
#define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff)

/* for function tracing recursion */
#define TRACE_INTERNAL_BIT		(1<<11)
#define TRACE_GLOBAL_BIT		(1<<12)

#define trace_recursion_set(bit)	do { (current)->trace_recursion |= (bit); } while (0)
#define trace_recursion_clear(bit)	do { (current)->trace_recursion &= ~(bit); } while (0)
#define trace_recursion_test(bit)	((current)->trace_recursion & (bit))

#endif /* _LINUX_KERNEL_TRACE_H */
+1 −1
Original line number Diff line number Diff line
@@ -227,7 +227,7 @@ int __trace_graph_entry(struct trace_array *tr,

static inline int ftrace_graph_ignore_irqs(void)
{
	if (!ftrace_graph_skip_irqs)
	if (!ftrace_graph_skip_irqs || trace_recursion_test(TRACE_IRQ_BIT))
		return 0;

	return in_irq();