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

Commit e1112b4d authored by Tom Zanussi's avatar Tom Zanussi Committed by Ingo Molnar
Browse files

tracing/filters: add run-time field descriptions to TRACE_EVENT_FORMAT events



This patch adds run-time field descriptions to all the event formats
exported using TRACE_EVENT_FORMAT.  It also hooks up all the tracers
that use them (i.e. the tracers in the 'ftrace subsystem') so they can
also have their output filtered by the event-filtering mechanism.

When I was testing this, there were a couple of things that fooled me
into thinking the filters weren't working, when actually they were -
I'll mention them here so others don't make the same mistakes (and file
bug reports. ;-)

One is that some of the tracers trace multiple events e.g. the
sched_switch tracer uses the context_switch and wakeup events, and if
you don't set filters on all of the traced events, the unfiltered output
from the events without filters on them can make it look like the
filtering as a whole isn't working properly, when actually it is doing
what it was asked to do - it just wasn't asked to do the right thing.

The other is that for the really high-volume tracers e.g. the function
tracer, the volume of filtered events can be so high that it pushes the
unfiltered events out of the ring buffer before they can be read so e.g.
cat'ing the trace file repeatedly shows either no output, or once in
awhile some output but that isn't there the next time you read the
trace, which isn't what you normally expect when reading the trace file.
If you read from the trace_pipe file though, you can catch them before
they disappear.

Changes from v1:

As suggested by Frederic Weisbecker:

- get rid of externs in functions
- added unlikely() to filter_check_discard()

Signed-off-by: default avatarTom Zanussi <tzanussi@gmail.com>
Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 66de7792
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -42,6 +42,7 @@ static inline void kmemtrace_alloc(enum kmemtrace_type_id type_id,
				   gfp_t gfp_flags,
				   gfp_t gfp_flags,
				   int node)
				   int node)
{
{
	struct ftrace_event_call *call = &event_kmem_alloc;
	struct trace_array *tr = kmemtrace_array;
	struct trace_array *tr = kmemtrace_array;
	struct kmemtrace_alloc_entry *entry;
	struct kmemtrace_alloc_entry *entry;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
@@ -62,6 +63,8 @@ static inline void kmemtrace_alloc(enum kmemtrace_type_id type_id,
	entry->gfp_flags	= gfp_flags;
	entry->gfp_flags	= gfp_flags;
	entry->node		= node;
	entry->node		= node;


	filter_check_discard(call, entry, event);

	ring_buffer_unlock_commit(tr->buffer, event);
	ring_buffer_unlock_commit(tr->buffer, event);


	trace_wake_up();
	trace_wake_up();
@@ -71,6 +74,7 @@ static inline void kmemtrace_free(enum kmemtrace_type_id type_id,
				  unsigned long call_site,
				  unsigned long call_site,
				  const void *ptr)
				  const void *ptr)
{
{
	struct ftrace_event_call *call = &event_kmem_free;
	struct trace_array *tr = kmemtrace_array;
	struct trace_array *tr = kmemtrace_array;
	struct kmemtrace_free_entry *entry;
	struct kmemtrace_free_entry *entry;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
@@ -86,6 +90,8 @@ static inline void kmemtrace_free(enum kmemtrace_type_id type_id,
	entry->call_site	= call_site;
	entry->call_site	= call_site;
	entry->ptr		= ptr;
	entry->ptr		= ptr;


	filter_check_discard(call, entry, event);

	ring_buffer_unlock_commit(tr->buffer, event);
	ring_buffer_unlock_commit(tr->buffer, event);


	trace_wake_up();
	trace_wake_up();
+25 −0
Original line number Original line Diff line number Diff line
@@ -898,6 +898,7 @@ trace_function(struct trace_array *tr,
	       unsigned long ip, unsigned long parent_ip, unsigned long flags,
	       unsigned long ip, unsigned long parent_ip, unsigned long flags,
	       int pc)
	       int pc)
{
{
	struct ftrace_event_call *call = &event_function;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct ftrace_entry *entry;
	struct ftrace_entry *entry;


@@ -912,6 +913,9 @@ trace_function(struct trace_array *tr,
	entry	= ring_buffer_event_data(event);
	entry	= ring_buffer_event_data(event);
	entry->ip			= ip;
	entry->ip			= ip;
	entry->parent_ip		= parent_ip;
	entry->parent_ip		= parent_ip;

	filter_check_discard(call, entry, event);

	ring_buffer_unlock_commit(tr->buffer, event);
	ring_buffer_unlock_commit(tr->buffer, event);
}
}


@@ -921,6 +925,7 @@ static int __trace_graph_entry(struct trace_array *tr,
				unsigned long flags,
				unsigned long flags,
				int pc)
				int pc)
{
{
	struct ftrace_event_call *call = &event_funcgraph_entry;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct ftrace_graph_ent_entry *entry;
	struct ftrace_graph_ent_entry *entry;


@@ -933,6 +938,7 @@ static int __trace_graph_entry(struct trace_array *tr,
		return 0;
		return 0;
	entry	= ring_buffer_event_data(event);
	entry	= ring_buffer_event_data(event);
	entry->graph_ent			= *trace;
	entry->graph_ent			= *trace;
	filter_check_discard(call, entry, event);
	ring_buffer_unlock_commit(global_trace.buffer, event);
	ring_buffer_unlock_commit(global_trace.buffer, event);


	return 1;
	return 1;
@@ -943,6 +949,7 @@ static void __trace_graph_return(struct trace_array *tr,
				unsigned long flags,
				unsigned long flags,
				int pc)
				int pc)
{
{
	struct ftrace_event_call *call = &event_funcgraph_exit;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct ftrace_graph_ret_entry *entry;
	struct ftrace_graph_ret_entry *entry;


@@ -955,6 +962,7 @@ static void __trace_graph_return(struct trace_array *tr,
		return;
		return;
	entry	= ring_buffer_event_data(event);
	entry	= ring_buffer_event_data(event);
	entry->ret				= *trace;
	entry->ret				= *trace;
	filter_check_discard(call, entry, event);
	ring_buffer_unlock_commit(global_trace.buffer, event);
	ring_buffer_unlock_commit(global_trace.buffer, event);
}
}
#endif
#endif
@@ -973,6 +981,7 @@ static void __ftrace_trace_stack(struct trace_array *tr,
				 int skip, int pc)
				 int skip, int pc)
{
{
#ifdef CONFIG_STACKTRACE
#ifdef CONFIG_STACKTRACE
	struct ftrace_event_call *call = &event_kernel_stack;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct stack_entry *entry;
	struct stack_entry *entry;
	struct stack_trace trace;
	struct stack_trace trace;
@@ -990,6 +999,7 @@ static void __ftrace_trace_stack(struct trace_array *tr,
	trace.entries		= entry->caller;
	trace.entries		= entry->caller;


	save_stack_trace(&trace);
	save_stack_trace(&trace);
	filter_check_discard(call, entry, event);
	ring_buffer_unlock_commit(tr->buffer, event);
	ring_buffer_unlock_commit(tr->buffer, event);
#endif
#endif
}
}
@@ -1015,6 +1025,7 @@ static void ftrace_trace_userstack(struct trace_array *tr,
				   unsigned long flags, int pc)
				   unsigned long flags, int pc)
{
{
#ifdef CONFIG_STACKTRACE
#ifdef CONFIG_STACKTRACE
	struct ftrace_event_call *call = &event_user_stack;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct userstack_entry *entry;
	struct userstack_entry *entry;
	struct stack_trace trace;
	struct stack_trace trace;
@@ -1036,6 +1047,7 @@ static void ftrace_trace_userstack(struct trace_array *tr,
	trace.entries		= entry->caller;
	trace.entries		= entry->caller;


	save_stack_trace_user(&trace);
	save_stack_trace_user(&trace);
	filter_check_discard(call, entry, event);
	ring_buffer_unlock_commit(tr->buffer, event);
	ring_buffer_unlock_commit(tr->buffer, event);
#endif
#endif
}
}
@@ -1052,6 +1064,7 @@ ftrace_trace_special(void *__tr,
		     unsigned long arg1, unsigned long arg2, unsigned long arg3,
		     unsigned long arg1, unsigned long arg2, unsigned long arg3,
		     int pc)
		     int pc)
{
{
	struct ftrace_event_call *call = &event_special;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct trace_array *tr = __tr;
	struct trace_array *tr = __tr;
	struct special_entry *entry;
	struct special_entry *entry;
@@ -1064,6 +1077,7 @@ ftrace_trace_special(void *__tr,
	entry->arg1			= arg1;
	entry->arg1			= arg1;
	entry->arg2			= arg2;
	entry->arg2			= arg2;
	entry->arg3			= arg3;
	entry->arg3			= arg3;
	filter_check_discard(call, entry, event);
	trace_buffer_unlock_commit(tr, event, 0, pc);
	trace_buffer_unlock_commit(tr, event, 0, pc);
}
}


@@ -1080,6 +1094,7 @@ tracing_sched_switch_trace(struct trace_array *tr,
			   struct task_struct *next,
			   struct task_struct *next,
			   unsigned long flags, int pc)
			   unsigned long flags, int pc)
{
{
	struct ftrace_event_call *call = &event_context_switch;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct ctx_switch_entry *entry;
	struct ctx_switch_entry *entry;


@@ -1095,6 +1110,9 @@ tracing_sched_switch_trace(struct trace_array *tr,
	entry->next_prio		= next->prio;
	entry->next_prio		= next->prio;
	entry->next_state		= next->state;
	entry->next_state		= next->state;
	entry->next_cpu	= task_cpu(next);
	entry->next_cpu	= task_cpu(next);

	filter_check_discard(call, entry, event);

	trace_buffer_unlock_commit(tr, event, flags, pc);
	trace_buffer_unlock_commit(tr, event, flags, pc);
}
}


@@ -1104,6 +1122,7 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
			   struct task_struct *curr,
			   struct task_struct *curr,
			   unsigned long flags, int pc)
			   unsigned long flags, int pc)
{
{
	struct ftrace_event_call *call = &event_wakeup;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct ctx_switch_entry *entry;
	struct ctx_switch_entry *entry;


@@ -1120,6 +1139,8 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
	entry->next_state		= wakee->state;
	entry->next_state		= wakee->state;
	entry->next_cpu			= task_cpu(wakee);
	entry->next_cpu			= task_cpu(wakee);


	filter_check_discard(call, entry, event);

	ring_buffer_unlock_commit(tr->buffer, event);
	ring_buffer_unlock_commit(tr->buffer, event);
	ftrace_trace_stack(tr, flags, 6, pc);
	ftrace_trace_stack(tr, flags, 6, pc);
	ftrace_trace_userstack(tr, flags, pc);
	ftrace_trace_userstack(tr, flags, pc);
@@ -1221,6 +1242,7 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
		(raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
		(raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
	static u32 trace_buf[TRACE_BUF_SIZE];
	static u32 trace_buf[TRACE_BUF_SIZE];


	struct ftrace_event_call *call = &event_bprint;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct trace_array *tr = &global_trace;
	struct trace_array *tr = &global_trace;
	struct trace_array_cpu *data;
	struct trace_array_cpu *data;
@@ -1260,6 +1282,7 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
	entry->fmt			= fmt;
	entry->fmt			= fmt;


	memcpy(entry->buf, trace_buf, sizeof(u32) * len);
	memcpy(entry->buf, trace_buf, sizeof(u32) * len);
	filter_check_discard(call, entry, event);
	ring_buffer_unlock_commit(tr->buffer, event);
	ring_buffer_unlock_commit(tr->buffer, event);


out_unlock:
out_unlock:
@@ -1279,6 +1302,7 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
	static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED;
	static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED;
	static char trace_buf[TRACE_BUF_SIZE];
	static char trace_buf[TRACE_BUF_SIZE];


	struct ftrace_event_call *call = &event_print;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct trace_array *tr = &global_trace;
	struct trace_array *tr = &global_trace;
	struct trace_array_cpu *data;
	struct trace_array_cpu *data;
@@ -1314,6 +1338,7 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)


	memcpy(&entry->buf, trace_buf, len);
	memcpy(&entry->buf, trace_buf, len);
	entry->buf[len] = 0;
	entry->buf[len] = 0;
	filter_check_discard(call, entry, event);
	ring_buffer_unlock_commit(tr->buffer, event);
	ring_buffer_unlock_commit(tr->buffer, event);


 out_unlock:
 out_unlock:
+20 −0
Original line number Original line Diff line number Diff line
@@ -866,6 +866,21 @@ extern void filter_free_subsystem_preds(struct event_subsystem *system);
extern int filter_add_subsystem_pred(struct event_subsystem *system,
extern int filter_add_subsystem_pred(struct event_subsystem *system,
				     struct filter_pred *pred);
				     struct filter_pred *pred);


static inline void
filter_check_discard(struct ftrace_event_call *call, void *rec,
		     struct ring_buffer_event *event)
{
	if (unlikely(call->preds) && !filter_match_preds(call, rec))
		ring_buffer_event_discard(event);
}

#define __common_field(type, item)					\
	ret = trace_define_field(event_call, #type, "common_" #item,	\
				 offsetof(typeof(field.ent), item),	\
				 sizeof(field.ent.item));		\
	if (ret)							\
		return ret;

void event_trace_printk(unsigned long ip, const char *fmt, ...);
void event_trace_printk(unsigned long ip, const char *fmt, ...);
extern struct ftrace_event_call __start_ftrace_events[];
extern struct ftrace_event_call __start_ftrace_events[];
extern struct ftrace_event_call __stop_ftrace_events[];
extern struct ftrace_event_call __stop_ftrace_events[];
@@ -897,4 +912,9 @@ do { \
		__trace_printk(ip, fmt, ##args);			\
		__trace_printk(ip, fmt, ##args);			\
} while (0)
} while (0)


#undef TRACE_EVENT_FORMAT
#define TRACE_EVENT_FORMAT(call, proto, args, fmt, tstruct, tpfmt)	\
	extern struct ftrace_event_call event_##call;
#include "trace_event_types.h"

#endif /* _LINUX_KERNEL_TRACE_H */
#endif /* _LINUX_KERNEL_TRACE_H */
+3 −0
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@ static struct trace_array *branch_tracer;
static void
static void
probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
{
{
	struct ftrace_event_call *call = &event_branch;
	struct trace_array *tr = branch_tracer;
	struct trace_array *tr = branch_tracer;
	struct ring_buffer_event *event;
	struct ring_buffer_event *event;
	struct trace_branch *entry;
	struct trace_branch *entry;
@@ -73,6 +74,8 @@ probe_likely_condition(struct ftrace_branch_data *f, int val, int expect)
	entry->line = f->line;
	entry->line = f->line;
	entry->correct = val == expect;
	entry->correct = val == expect;


	filter_check_discard(call, entry, event);

	ring_buffer_unlock_commit(tr->buffer, event);
	ring_buffer_unlock_commit(tr->buffer, event);


 out:
 out:
+4 −2
Original line number Original line Diff line number Diff line
@@ -122,8 +122,10 @@ TRACE_EVENT_FORMAT(print, TRACE_PRINT, print_entry, ignore,
TRACE_EVENT_FORMAT(branch, TRACE_BRANCH, trace_branch, ignore,
TRACE_EVENT_FORMAT(branch, TRACE_BRANCH, trace_branch, ignore,
	TRACE_STRUCT(
	TRACE_STRUCT(
		TRACE_FIELD(unsigned int, line, line)
		TRACE_FIELD(unsigned int, line, line)
		TRACE_FIELD_SPECIAL(char func[TRACE_FUNC_SIZE+1], func, func)
		TRACE_FIELD_SPECIAL(char func[TRACE_FUNC_SIZE+1], func,
		TRACE_FIELD_SPECIAL(char file[TRACE_FUNC_SIZE+1], file, file)
				    TRACE_FUNC_SIZE+1, func)
		TRACE_FIELD_SPECIAL(char file[TRACE_FUNC_SIZE+1], file,
				    TRACE_FUNC_SIZE+1, file)
		TRACE_FIELD(char, correct, correct)
		TRACE_FIELD(char, correct, correct)
	),
	),
	TP_RAW_FMT("%u:%s:%s (%u)")
	TP_RAW_FMT("%u:%s:%s (%u)")
Loading