diff options
author | Tom Zanussi <tzanussi@gmail.com> | 2009-03-22 04:30:39 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-22 13:11:22 -0400 |
commit | cf027f645e6aee4f0ca6197a6b6a57f327fdb13f (patch) | |
tree | f8a20e8707967db5d9140f9069426f410a30dd32 /kernel/trace | |
parent | 0cf53ff62b3e9e491ff5e5f05b193fb6ce643047 (diff) |
tracing: add run-time field descriptions for event filtering
This patch makes the field descriptions defined for event tracing
available at run-time, for the event-filtering mechanism introduced
in a subsequent patch.
The common event fields are prepended with 'common_' in the format
display, allowing them to be distinguished from the other fields
that might internally have same name and can therefore be
unambiguously used in filters.
Signed-off-by: Tom Zanussi <tzanussi@gmail.com>
Acked-by: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <1237710639.7703.46.camel@charm-linux>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace.h | 30 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 40 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_2.h | 45 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_3.h | 2 |
4 files changed, 107 insertions, 10 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 7cfb741be200..9288dc7ad14f 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -775,16 +775,26 @@ enum { | |||
775 | TRACE_EVENT_TYPE_RAW = 2, | 775 | TRACE_EVENT_TYPE_RAW = 2, |
776 | }; | 776 | }; |
777 | 777 | ||
778 | struct ftrace_event_field { | ||
779 | struct list_head link; | ||
780 | char *name; | ||
781 | char *type; | ||
782 | int offset; | ||
783 | int size; | ||
784 | }; | ||
785 | |||
778 | struct ftrace_event_call { | 786 | struct ftrace_event_call { |
779 | char *name; | 787 | char *name; |
780 | char *system; | 788 | char *system; |
781 | struct dentry *dir; | 789 | struct dentry *dir; |
782 | int enabled; | 790 | int enabled; |
783 | int (*regfunc)(void); | 791 | int (*regfunc)(void); |
784 | void (*unregfunc)(void); | 792 | void (*unregfunc)(void); |
785 | int id; | 793 | int id; |
786 | int (*raw_init)(void); | 794 | int (*raw_init)(void); |
787 | int (*show_format)(struct trace_seq *s); | 795 | int (*show_format)(struct trace_seq *s); |
796 | int (*define_fields)(void); | ||
797 | struct list_head fields; | ||
788 | 798 | ||
789 | #ifdef CONFIG_EVENT_PROFILE | 799 | #ifdef CONFIG_EVENT_PROFILE |
790 | atomic_t profile_count; | 800 | atomic_t profile_count; |
@@ -793,6 +803,8 @@ struct ftrace_event_call { | |||
793 | #endif | 803 | #endif |
794 | }; | 804 | }; |
795 | 805 | ||
806 | int trace_define_field(struct ftrace_event_call *call, char *type, | ||
807 | char *name, int offset, int size); | ||
796 | void event_trace_printk(unsigned long ip, const char *fmt, ...); | 808 | void event_trace_printk(unsigned long ip, const char *fmt, ...); |
797 | extern struct ftrace_event_call __start_ftrace_events[]; | 809 | extern struct ftrace_event_call __start_ftrace_events[]; |
798 | extern struct ftrace_event_call __stop_ftrace_events[]; | 810 | extern struct ftrace_event_call __stop_ftrace_events[]; |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 3047b56f6637..961b057da28b 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -19,6 +19,34 @@ | |||
19 | 19 | ||
20 | static DEFINE_MUTEX(event_mutex); | 20 | static DEFINE_MUTEX(event_mutex); |
21 | 21 | ||
22 | int trace_define_field(struct ftrace_event_call *call, char *type, | ||
23 | char *name, int offset, int size) | ||
24 | { | ||
25 | struct ftrace_event_field *field; | ||
26 | |||
27 | field = kmalloc(sizeof(*field), GFP_KERNEL); | ||
28 | if (!field) | ||
29 | goto err; | ||
30 | field->name = kstrdup(name, GFP_KERNEL); | ||
31 | if (!field->name) | ||
32 | goto err; | ||
33 | field->type = kstrdup(type, GFP_KERNEL); | ||
34 | if (!field->type) | ||
35 | goto err; | ||
36 | field->offset = offset; | ||
37 | field->size = size; | ||
38 | list_add(&field->link, &call->fields); | ||
39 | |||
40 | return 0; | ||
41 | err: | ||
42 | if (field) { | ||
43 | kfree(field->name); | ||
44 | kfree(field->type); | ||
45 | } | ||
46 | kfree(field); | ||
47 | return -ENOMEM; | ||
48 | } | ||
49 | |||
22 | static void ftrace_clear_events(void) | 50 | static void ftrace_clear_events(void) |
23 | { | 51 | { |
24 | struct ftrace_event_call *call = (void *)__start_ftrace_events; | 52 | struct ftrace_event_call *call = (void *)__start_ftrace_events; |
@@ -343,7 +371,8 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
343 | 371 | ||
344 | #undef FIELD | 372 | #undef FIELD |
345 | #define FIELD(type, name) \ | 373 | #define FIELD(type, name) \ |
346 | #type, #name, offsetof(typeof(field), name), sizeof(field.name) | 374 | #type, "common_" #name, offsetof(typeof(field), name), \ |
375 | sizeof(field.name) | ||
347 | 376 | ||
348 | static int trace_write_header(struct trace_seq *s) | 377 | static int trace_write_header(struct trace_seq *s) |
349 | { | 378 | { |
@@ -581,6 +610,15 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events) | |||
581 | call->name); | 610 | call->name); |
582 | } | 611 | } |
583 | 612 | ||
613 | if (call->define_fields) { | ||
614 | ret = call->define_fields(); | ||
615 | if (ret < 0) { | ||
616 | pr_warning("Could not initialize trace point" | ||
617 | " events/%s\n", call->name); | ||
618 | return ret; | ||
619 | } | ||
620 | } | ||
621 | |||
584 | /* A trace may not want to export its format */ | 622 | /* A trace may not want to export its format */ |
585 | if (!call->show_format) | 623 | if (!call->show_format) |
586 | return 0; | 624 | return 0; |
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h index 5117c43f5c67..30743f7d4110 100644 --- a/kernel/trace/trace_events_stage_2.h +++ b/kernel/trace/trace_events_stage_2.h | |||
@@ -129,3 +129,48 @@ ftrace_format_##call(struct trace_seq *s) \ | |||
129 | } | 129 | } |
130 | 130 | ||
131 | #include <trace/trace_event_types.h> | 131 | #include <trace/trace_event_types.h> |
132 | |||
133 | #undef __field | ||
134 | #define __field(type, item) \ | ||
135 | ret = trace_define_field(event_call, #type, #item, \ | ||
136 | offsetof(typeof(field), item), \ | ||
137 | sizeof(field.item)); \ | ||
138 | if (ret) \ | ||
139 | return ret; | ||
140 | |||
141 | #undef __array | ||
142 | #define __array(type, item, len) \ | ||
143 | ret = trace_define_field(event_call, #type "[" #len "]", #item, \ | ||
144 | offsetof(typeof(field), item), \ | ||
145 | sizeof(field.item)); \ | ||
146 | if (ret) \ | ||
147 | return ret; | ||
148 | |||
149 | #define __common_field(type, item) \ | ||
150 | ret = trace_define_field(event_call, #type, "common_" #item, \ | ||
151 | offsetof(typeof(field.ent), item), \ | ||
152 | sizeof(field.ent.item)); \ | ||
153 | if (ret) \ | ||
154 | return ret; | ||
155 | |||
156 | #undef TRACE_EVENT | ||
157 | #define TRACE_EVENT(call, proto, args, tstruct, func, print) \ | ||
158 | int \ | ||
159 | ftrace_define_fields_##call(void) \ | ||
160 | { \ | ||
161 | struct ftrace_raw_##call field; \ | ||
162 | struct ftrace_event_call *event_call = &event_##call; \ | ||
163 | int ret; \ | ||
164 | \ | ||
165 | __common_field(unsigned char, type); \ | ||
166 | __common_field(unsigned char, flags); \ | ||
167 | __common_field(unsigned char, preempt_count); \ | ||
168 | __common_field(int, pid); \ | ||
169 | __common_field(int, tgid); \ | ||
170 | \ | ||
171 | tstruct; \ | ||
172 | \ | ||
173 | return ret; \ | ||
174 | } | ||
175 | |||
176 | #include <trace/trace_event_types.h> | ||
diff --git a/kernel/trace/trace_events_stage_3.h b/kernel/trace/trace_events_stage_3.h index 6b3261ca988c..468938f70141 100644 --- a/kernel/trace/trace_events_stage_3.h +++ b/kernel/trace/trace_events_stage_3.h | |||
@@ -252,6 +252,7 @@ static int ftrace_raw_init_event_##call(void) \ | |||
252 | if (!id) \ | 252 | if (!id) \ |
253 | return -ENODEV; \ | 253 | return -ENODEV; \ |
254 | event_##call.id = id; \ | 254 | event_##call.id = id; \ |
255 | INIT_LIST_HEAD(&event_##call.fields); \ | ||
255 | return 0; \ | 256 | return 0; \ |
256 | } \ | 257 | } \ |
257 | \ | 258 | \ |
@@ -264,6 +265,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
264 | .regfunc = ftrace_raw_reg_event_##call, \ | 265 | .regfunc = ftrace_raw_reg_event_##call, \ |
265 | .unregfunc = ftrace_raw_unreg_event_##call, \ | 266 | .unregfunc = ftrace_raw_unreg_event_##call, \ |
266 | .show_format = ftrace_format_##call, \ | 267 | .show_format = ftrace_format_##call, \ |
268 | .define_fields = ftrace_define_fields_##call, \ | ||
267 | _TRACE_PROFILE_INIT(call) \ | 269 | _TRACE_PROFILE_INIT(call) \ |
268 | } | 270 | } |
269 | 271 | ||