diff options
-rw-r--r-- | include/linux/ftrace_event.h | 13 | ||||
-rw-r--r-- | include/trace/ftrace.h | 14 | ||||
-rw-r--r-- | kernel/trace/trace_output.c | 39 |
3 files changed, 65 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 | \ |
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 7136420603aa..a4840c260c89 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c | |||
@@ -15,6 +15,9 @@ | |||
15 | #define EVENT_HASHSIZE 128 | 15 | #define EVENT_HASHSIZE 128 |
16 | 16 | ||
17 | static DECLARE_RWSEM(trace_event_mutex); | 17 | static DECLARE_RWSEM(trace_event_mutex); |
18 | |||
19 | DEFINE_PER_CPU(struct trace_seq, ftrace_event_seq); | ||
20 | |||
18 | static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly; | 21 | static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly; |
19 | 22 | ||
20 | static int next_event_type = __TRACE_LAST_TYPE + 1; | 23 | static int next_event_type = __TRACE_LAST_TYPE + 1; |
@@ -212,6 +215,42 @@ int trace_seq_path(struct trace_seq *s, struct path *path) | |||
212 | return 0; | 215 | return 0; |
213 | } | 216 | } |
214 | 217 | ||
218 | const char * | ||
219 | ftrace_print_flags_seq(struct trace_seq *p, const char *delim, | ||
220 | unsigned long flags, | ||
221 | const struct trace_print_flags *flag_array) | ||
222 | { | ||
223 | unsigned long mask; | ||
224 | const char *str; | ||
225 | int i; | ||
226 | |||
227 | trace_seq_init(p); | ||
228 | |||
229 | for (i = 0; flag_array[i].name && flags; i++) { | ||
230 | |||
231 | mask = flag_array[i].mask; | ||
232 | if ((flags & mask) != mask) | ||
233 | continue; | ||
234 | |||
235 | str = flag_array[i].name; | ||
236 | flags &= ~mask; | ||
237 | if (p->len && delim) | ||
238 | trace_seq_puts(p, delim); | ||
239 | trace_seq_puts(p, str); | ||
240 | } | ||
241 | |||
242 | /* check for left over flags */ | ||
243 | if (flags) { | ||
244 | if (p->len && delim) | ||
245 | trace_seq_puts(p, delim); | ||
246 | trace_seq_printf(p, "0x%lx", flags); | ||
247 | } | ||
248 | |||
249 | trace_seq_putc(p, 0); | ||
250 | |||
251 | return p->buffer; | ||
252 | } | ||
253 | |||
215 | #ifdef CONFIG_KRETPROBES | 254 | #ifdef CONFIG_KRETPROBES |
216 | static inline const char *kretprobed(const char *name) | 255 | static inline const char *kretprobed(const char *name) |
217 | { | 256 | { |