diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-05-26 14:25:22 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-05-26 14:25:22 -0400 |
commit | be74b73a57645cc253d881ab0c1014eb64b9cf22 (patch) | |
tree | 83f14ae9a43fe98a1363d30d20d60245e1115382 /include | |
parent | 0e907c99391362385c8e3af2c43b904dd1fd5d73 (diff) |
tracing: add __print_flags for events
Developers have been asking for the ability in the ftrace event tracer
to display names of bits in a flags variable.
Instead of printing out c2, it would be easier to read FOO|BAR|GOO,
assuming that FOO is bit 1, BAR is bit 6 and GOO is bit 7.
Some examples where this would be useful are the state flags in a context
switch, kmalloc flags, and even permision flags in accessing files.
[
v2 changes include:
Frederic Weisbecker's idea of using a mask instead of bits,
thus we can output GFP_KERNEL instead of GPF_WAIT|GFP_IO|GFP_FS.
Li Zefan's idea of allowing the caller of __print_flags to add their
own delimiter (or no delimiter) where we can get for file permissions
rwx instead of r|w|x.
]
[
v3 changes:
Christoph Hellwig's idea of using an array instead of va_args.
]
[ Impact: better displaying of flags in trace output ]
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/ftrace_event.h | 13 | ||||
-rw-r--r-- | include/trace/ftrace.h | 14 |
2 files changed, 26 insertions, 1 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index bae51ddfabd3..4b58cf1a11c2 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h | |||
@@ -3,12 +3,23 @@ | |||
3 | 3 | ||
4 | #include <linux/trace_seq.h> | 4 | #include <linux/trace_seq.h> |
5 | #include <linux/ring_buffer.h> | 5 | #include <linux/ring_buffer.h> |
6 | 6 | #include <linux/percpu.h> | |
7 | 7 | ||
8 | struct trace_array; | 8 | struct trace_array; |
9 | struct tracer; | 9 | struct tracer; |
10 | struct dentry; | 10 | struct dentry; |
11 | 11 | ||
12 | DECLARE_PER_CPU(struct trace_seq, ftrace_event_seq); | ||
13 | |||
14 | struct trace_print_flags { | ||
15 | unsigned long mask; | ||
16 | const char *name; | ||
17 | }; | ||
18 | |||
19 | const char *ftrace_print_flags_seq(struct trace_seq *p, const char *delim, | ||
20 | unsigned long flags, | ||
21 | const struct trace_print_flags *flag_array); | ||
22 | |||
12 | /* | 23 | /* |
13 | * The trace entry - the most basic unit of tracing. This is what | 24 | * The trace entry - the most basic unit of tracing. This is what |
14 | * is printed in the end as a single line in the trace output, such as: | 25 | * is printed in the end as a single line in the trace output, such as: |
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index b5ff2e8229ec..22c94719c569 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h | |||
@@ -87,6 +87,7 @@ | |||
87 | * struct trace_seq *s = &iter->seq; | 87 | * struct trace_seq *s = &iter->seq; |
88 | * struct ftrace_raw_<call> *field; <-- defined in stage 1 | 88 | * struct ftrace_raw_<call> *field; <-- defined in stage 1 |
89 | * struct trace_entry *entry; | 89 | * struct trace_entry *entry; |
90 | * struct trace_seq *p; | ||
90 | * int ret; | 91 | * int ret; |
91 | * | 92 | * |
92 | * entry = iter->ent; | 93 | * entry = iter->ent; |
@@ -98,7 +99,9 @@ | |||
98 | * | 99 | * |
99 | * field = (typeof(field))entry; | 100 | * field = (typeof(field))entry; |
100 | * | 101 | * |
102 | * p = get_cpu_var(ftrace_event_seq); | ||
101 | * ret = trace_seq_printf(s, <TP_printk> "\n"); | 103 | * ret = trace_seq_printf(s, <TP_printk> "\n"); |
104 | * put_cpu(); | ||
102 | * if (!ret) | 105 | * if (!ret) |
103 | * return TRACE_TYPE_PARTIAL_LINE; | 106 | * return TRACE_TYPE_PARTIAL_LINE; |
104 | * | 107 | * |
@@ -119,6 +122,14 @@ | |||
119 | #undef __get_str | 122 | #undef __get_str |
120 | #define __get_str(field) ((char *)__entry + __entry->__str_loc_##field) | 123 | #define __get_str(field) ((char *)__entry + __entry->__str_loc_##field) |
121 | 124 | ||
125 | #undef __print_flags | ||
126 | #define __print_flags(flag, delim, flag_array...) \ | ||
127 | ({ \ | ||
128 | static const struct trace_print_flags flags[] = \ | ||
129 | { flag_array, { -1, NULL }}; \ | ||
130 | ftrace_print_flags_seq(p, delim, flag, flags); \ | ||
131 | }) | ||
132 | |||
122 | #undef TRACE_EVENT | 133 | #undef TRACE_EVENT |
123 | #define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ | 134 | #define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ |
124 | enum print_line_t \ | 135 | enum print_line_t \ |
@@ -127,6 +138,7 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \ | |||
127 | struct trace_seq *s = &iter->seq; \ | 138 | struct trace_seq *s = &iter->seq; \ |
128 | struct ftrace_raw_##call *field; \ | 139 | struct ftrace_raw_##call *field; \ |
129 | struct trace_entry *entry; \ | 140 | struct trace_entry *entry; \ |
141 | struct trace_seq *p; \ | ||
130 | int ret; \ | 142 | int ret; \ |
131 | \ | 143 | \ |
132 | entry = iter->ent; \ | 144 | entry = iter->ent; \ |
@@ -138,7 +150,9 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \ | |||
138 | \ | 150 | \ |
139 | field = (typeof(field))entry; \ | 151 | field = (typeof(field))entry; \ |
140 | \ | 152 | \ |
153 | p = &get_cpu_var(ftrace_event_seq); \ | ||
141 | ret = trace_seq_printf(s, #call ": " print); \ | 154 | ret = trace_seq_printf(s, #call ": " print); \ |
155 | put_cpu(); \ | ||
142 | if (!ret) \ | 156 | if (!ret) \ |
143 | return TRACE_TYPE_PARTIAL_LINE; \ | 157 | return TRACE_TYPE_PARTIAL_LINE; \ |
144 | \ | 158 | \ |