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

Commit 0c564a53 authored by Steven Rostedt (Red Hat)'s avatar Steven Rostedt (Red Hat) Committed by Steven Rostedt
Browse files

tracing: Add TRACE_DEFINE_ENUM() macro to map enums to their values

Several tracepoints use the helper functions __print_symbolic() or
__print_flags() and pass in enums that do the mapping between the
binary data stored and the value to print. This works well for reading
the ASCII trace files, but when the data is read via userspace tools
such as perf and trace-cmd, the conversion of the binary value to a
human string format is lost if an enum is used, as userspace does not
have access to what the ENUM is.

For example, the tracepoint trace_tlb_flush() has:

 __print_symbolic(REC->reason,
    { TLB_FLUSH_ON_TASK_SWITCH, "flush on task switch" },
    { TLB_REMOTE_SHOOTDOWN, "remote shootdown" },
    { TLB_LOCAL_SHOOTDOWN, "local shootdown" },
    { TLB_LOCAL_MM_SHOOTDOWN, "local mm shootdown" })

Which maps the enum values to the strings they represent. But perf and
trace-cmd do no know what value TLB_LOCAL_MM_SHOOTDOWN is, and would
not be able to map it.

With TRACE_DEFINE_ENUM(), developers can place these in the event header
files and ftrace will convert the enums to their values:

By adding:

 TRACE_DEFINE_ENUM(TLB_FLUSH_ON_TASK_SWITCH);
 TRACE_DEFINE_ENUM(TLB_REMOTE_SHOOTDOWN);
 TRACE_DEFINE_ENUM(TLB_LOCAL_SHOOTDOWN);
 TRACE_DEFINE_ENUM(TLB_LOCAL_MM_SHOOTDOWN);

 $ cat /sys/kernel/debug/tracing/events/tlb/tlb_flush/format
[...]
 __print_symbolic(REC->reason,
    { 0, "flush on task switch" },
    { 1, "remote shootdown" },
    { 2, "local shootdown" },
    { 3, "local mm shootdown" })

The above is what userspace expects to see, and tools do not need to
be modified to parse them.

Link: http://lkml.kernel.org/r/20150403013802.220157513@goodmis.org



Cc: Guilherme Cox <cox@computer.org>
Cc: Tony Luck <tony.luck@gmail.com>
Cc: Xie XiuQi <xiexiuqi@huawei.com>
Acked-by: default avatarNamhyung Kim <namhyung@kernel.org>
Reviewed-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Tested-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 88920427
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -124,7 +124,10 @@
#define FTRACE_EVENTS()	. = ALIGN(8);					\
			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
			*(_ftrace_events)				\
			VMLINUX_SYMBOL(__stop_ftrace_events) = .;
			VMLINUX_SYMBOL(__stop_ftrace_events) = .;	\
			VMLINUX_SYMBOL(__start_ftrace_enum_maps) = .;	\
			*(_ftrace_enum_map)				\
			VMLINUX_SYMBOL(__stop_ftrace_enum_maps) = .;
#else
#define FTRACE_EVENTS()
#endif
+1 −1
Original line number Diff line number Diff line
@@ -285,7 +285,7 @@ struct ftrace_event_call {
		struct tracepoint	*tp;
	};
	struct trace_event	event;
	const char		*print_fmt;
	char			*print_fmt;
	struct event_filter	*filter;
	void			*mod;
	void			*data;
+8 −0
Original line number Diff line number Diff line
@@ -36,6 +36,12 @@ struct tracepoint {
	struct tracepoint_func __rcu *funcs;
};

struct trace_enum_map {
	const char		*system;
	const char		*enum_string;
	unsigned long		enum_value;
};

extern int
tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
extern int
@@ -87,6 +93,8 @@ extern void syscall_unregfunc(void);

#define PARAMS(args...) args

#define TRACE_DEFINE_ENUM(x)

#endif /* _LINUX_TRACEPOINT_H */

/*
+19 −3
Original line number Diff line number Diff line
@@ -33,6 +33,19 @@

TRACE_MAKE_SYSTEM_STR();

#undef TRACE_DEFINE_ENUM
#define TRACE_DEFINE_ENUM(a)				\
	static struct trace_enum_map __used __initdata	\
	__##TRACE_SYSTEM##_##a =			\
	{						\
		.system = TRACE_SYSTEM_STRING,		\
		.enum_string = #a,			\
		.enum_value = a				\
	};						\
	static struct trace_enum_map __used		\
	__attribute__((section("_ftrace_enum_map")))	\
	*TRACE_SYSTEM##_##a = &__##TRACE_SYSTEM##_##a

/*
 * DECLARE_EVENT_CLASS can be used to add a generic function
 * handlers for events. That is, if all events have the same
@@ -136,6 +149,9 @@ TRACE_MAKE_SYSTEM_STR();
 * The size of an array is also encoded, in the higher 16 bits of <item>.
 */

#undef TRACE_DEFINE_ENUM
#define TRACE_DEFINE_ENUM(a)

#undef __field
#define __field(type, item)

@@ -553,7 +569,7 @@ static inline notrace int ftrace_get_offsets_##call( \
 *	.trace			= ftrace_raw_output_<call>, <-- stage 2
 * };
 *
 * static const char print_fmt_<call>[] = <TP_printk>;
 * static char print_fmt_<call>[] = <TP_printk>;
 *
 * static struct ftrace_event_class __used event_class_<template> = {
 *	.system			= "<system>",
@@ -704,7 +720,7 @@ static inline void ftrace_test_probe_##call(void) \
#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print)	\
_TRACE_PERF_PROTO(call, PARAMS(proto));					\
static const char print_fmt_##call[] = print;				\
static char print_fmt_##call[] = print;					\
static struct ftrace_event_class __used __refdata event_class_##call = { \
	.system			= TRACE_SYSTEM_STRING,			\
	.define_fields		= ftrace_define_fields_##call,		\
@@ -733,7 +749,7 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
#undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, call, proto, args, print)		\
									\
static const char print_fmt_##call[] = print;				\
static char print_fmt_##call[] = print;					\
									\
static struct ftrace_event_call __used event_##call = {			\
	.class			= &event_class_##template,		\
+25 −1
Original line number Diff line number Diff line
@@ -3908,6 +3908,20 @@ static const struct file_operations tracing_saved_cmdlines_size_fops = {
	.write		= tracing_saved_cmdlines_size_write,
};

static void
trace_insert_enum_map(struct trace_enum_map **start, struct trace_enum_map **stop)
{
	struct trace_enum_map **map;
	int len = stop - start;

	if (len <= 0)
		return;

	map = start;

	trace_event_enum_update(map, len);
}

static ssize_t
tracing_set_trace_read(struct file *filp, char __user *ubuf,
		       size_t cnt, loff_t *ppos)
@@ -6542,6 +6556,14 @@ struct dentry *tracing_init_dentry(void)
	return tr->dir;
}

extern struct trace_enum_map *__start_ftrace_enum_maps[];
extern struct trace_enum_map *__stop_ftrace_enum_maps[];

static void __init trace_enum_init(void)
{
	trace_insert_enum_map(__start_ftrace_enum_maps, __stop_ftrace_enum_maps);
}

static __init int tracer_init_debugfs(void)
{
	struct dentry *d_tracer;
@@ -6566,6 +6588,8 @@ static __init int tracer_init_debugfs(void)
	trace_create_file("saved_cmdlines_size", 0644, d_tracer,
			  NULL, &tracing_saved_cmdlines_size_fops);

	trace_enum_init();

#ifdef CONFIG_DYNAMIC_FTRACE
	trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
			&ftrace_update_tot_cnt, &tracing_dyn_info_fops);
Loading