aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-04-10 13:52:20 -0400
committerSteven Rostedt <rostedt@goodmis.org>2009-04-14 12:58:00 -0400
commita59fd6027218bd7c994e39d14afe0242f895144f (patch)
treec22e6ff2924726319eac84c480eca72066bad660
parentf42c85e74faa422cf0bc747ed808681145448f88 (diff)
tracing/events: convert event call sites to use a link list
Impact: makes it possible to define events in modules The events are created by reading down the section that they are linked in by the macros. But this is not scalable to modules. This patch converts the manipulations to use a global link list, and on boot up it adds the items in the section to the list. This change will allow modules to add their tracing events to the list as well. Note, this change alone does not permit modules to use the TRACE_EVENT macros, but the change is needed for them to eventually do so. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--include/linux/ftrace_event.h1
-rw-r--r--kernel/trace/trace.h13
-rw-r--r--kernel/trace/trace_event_profile.c4
-rw-r--r--kernel/trace/trace_events.c51
-rw-r--r--kernel/trace/trace_events_filter.c8
5 files changed, 39 insertions, 38 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 496b76d9f9d8..17810853b4f8 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -83,6 +83,7 @@ void trace_current_buffer_discard_commit(struct ring_buffer_event *event);
83void tracing_record_cmdline(struct task_struct *tsk); 83void tracing_record_cmdline(struct task_struct *tsk);
84 84
85struct ftrace_event_call { 85struct ftrace_event_call {
86 struct list_head list;
86 char *name; 87 char *name;
87 char *system; 88 char *system;
88 struct dentry *dir; 89 struct dentry *dir;
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 6bcdf4af9b2d..8817c18ef97a 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -739,11 +739,6 @@ struct event_subsystem {
739 struct filter_pred **preds; 739 struct filter_pred **preds;
740}; 740};
741 741
742#define events_for_each(event) \
743 for (event = __start_ftrace_events; \
744 (unsigned long)event < (unsigned long)__stop_ftrace_events; \
745 event++)
746
747struct filter_pred; 742struct filter_pred;
748 743
749typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event); 744typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event);
@@ -785,13 +780,7 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
785 return 0; 780 return 0;
786} 781}
787 782
788extern struct ftrace_event_call __start_ftrace_events[]; 783extern struct list_head ftrace_events;
789extern struct ftrace_event_call __stop_ftrace_events[];
790
791#define for_each_event(event) \
792 for (event = __start_ftrace_events; \
793 (unsigned long)event < (unsigned long)__stop_ftrace_events; \
794 event++)
795 784
796extern const char *__start___trace_bprintk_fmt[]; 785extern const char *__start___trace_bprintk_fmt[];
797extern const char *__stop___trace_bprintk_fmt[]; 786extern const char *__stop___trace_bprintk_fmt[];
diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_profile.c
index 199de9c74229..7bf2ad65eee5 100644
--- a/kernel/trace/trace_event_profile.c
+++ b/kernel/trace/trace_event_profile.c
@@ -11,7 +11,7 @@ int ftrace_profile_enable(int event_id)
11{ 11{
12 struct ftrace_event_call *event; 12 struct ftrace_event_call *event;
13 13
14 for_each_event(event) { 14 list_for_each_entry(event, &ftrace_events, list) {
15 if (event->id == event_id) 15 if (event->id == event_id)
16 return event->profile_enable(event); 16 return event->profile_enable(event);
17 } 17 }
@@ -23,7 +23,7 @@ void ftrace_profile_disable(int event_id)
23{ 23{
24 struct ftrace_event_call *event; 24 struct ftrace_event_call *event;
25 25
26 for_each_event(event) { 26 list_for_each_entry(event, &ftrace_events, list) {
27 if (event->id == event_id) 27 if (event->id == event_id)
28 return event->profile_disable(event); 28 return event->profile_disable(event);
29 } 29 }
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index ead68ac99191..5c66aaff07c1 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -19,6 +19,8 @@
19 19
20static DEFINE_MUTEX(event_mutex); 20static DEFINE_MUTEX(event_mutex);
21 21
22LIST_HEAD(ftrace_events);
23
22int trace_define_field(struct ftrace_event_call *call, char *type, 24int trace_define_field(struct ftrace_event_call *call, char *type,
23 char *name, int offset, int size) 25 char *name, int offset, int size)
24{ 26{
@@ -54,16 +56,14 @@ err:
54 56
55static void ftrace_clear_events(void) 57static void ftrace_clear_events(void)
56{ 58{
57 struct ftrace_event_call *call = (void *)__start_ftrace_events; 59 struct ftrace_event_call *call;
58
59 60
60 while ((unsigned long)call < (unsigned long)__stop_ftrace_events) { 61 list_for_each_entry(call, &ftrace_events, list) {
61 62
62 if (call->enabled) { 63 if (call->enabled) {
63 call->enabled = 0; 64 call->enabled = 0;
64 call->unregfunc(); 65 call->unregfunc();
65 } 66 }
66 call++;
67 } 67 }
68} 68}
69 69
@@ -89,7 +89,7 @@ static void ftrace_event_enable_disable(struct ftrace_event_call *call,
89 89
90static int ftrace_set_clr_event(char *buf, int set) 90static int ftrace_set_clr_event(char *buf, int set)
91{ 91{
92 struct ftrace_event_call *call = __start_ftrace_events; 92 struct ftrace_event_call *call;
93 char *event = NULL, *sub = NULL, *match; 93 char *event = NULL, *sub = NULL, *match;
94 int ret = -EINVAL; 94 int ret = -EINVAL;
95 95
@@ -118,7 +118,7 @@ static int ftrace_set_clr_event(char *buf, int set)
118 } 118 }
119 119
120 mutex_lock(&event_mutex); 120 mutex_lock(&event_mutex);
121 for_each_event(call) { 121 list_for_each_entry(call, &ftrace_events, list) {
122 122
123 if (!call->name || !call->regfunc) 123 if (!call->name || !call->regfunc)
124 continue; 124 continue;
@@ -224,15 +224,17 @@ ftrace_event_write(struct file *file, const char __user *ubuf,
224static void * 224static void *
225t_next(struct seq_file *m, void *v, loff_t *pos) 225t_next(struct seq_file *m, void *v, loff_t *pos)
226{ 226{
227 struct ftrace_event_call *call = m->private; 227 struct list_head *list = m->private;
228 struct ftrace_event_call *next = call; 228 struct ftrace_event_call *call;
229 229
230 (*pos)++; 230 (*pos)++;
231 231
232 for (;;) { 232 for (;;) {
233 if ((unsigned long)call >= (unsigned long)__stop_ftrace_events) 233 if (list == &ftrace_events)
234 return NULL; 234 return NULL;
235 235
236 call = list_entry(list, struct ftrace_event_call, list);
237
236 /* 238 /*
237 * The ftrace subsystem is for showing formats only. 239 * The ftrace subsystem is for showing formats only.
238 * They can not be enabled or disabled via the event files. 240 * They can not be enabled or disabled via the event files.
@@ -240,11 +242,10 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
240 if (call->regfunc) 242 if (call->regfunc)
241 break; 243 break;
242 244
243 call++; 245 list = list->next;
244 next = call;
245 } 246 }
246 247
247 m->private = ++next; 248 m->private = list->next;
248 249
249 return call; 250 return call;
250} 251}
@@ -257,22 +258,23 @@ static void *t_start(struct seq_file *m, loff_t *pos)
257static void * 258static void *
258s_next(struct seq_file *m, void *v, loff_t *pos) 259s_next(struct seq_file *m, void *v, loff_t *pos)
259{ 260{
260 struct ftrace_event_call *call = m->private; 261 struct list_head *list = m->private;
261 struct ftrace_event_call *next; 262 struct ftrace_event_call *call;
262 263
263 (*pos)++; 264 (*pos)++;
264 265
265 retry: 266 retry:
266 if ((unsigned long)call >= (unsigned long)__stop_ftrace_events) 267 if (list == &ftrace_events)
267 return NULL; 268 return NULL;
268 269
270 call = list_entry(list, struct ftrace_event_call, list);
271
269 if (!call->enabled) { 272 if (!call->enabled) {
270 call++; 273 list = list->next;
271 goto retry; 274 goto retry;
272 } 275 }
273 276
274 next = call; 277 m->private = list->next;
275 m->private = ++next;
276 278
277 return call; 279 return call;
278} 280}
@@ -312,7 +314,7 @@ ftrace_event_seq_open(struct inode *inode, struct file *file)
312 if (!ret) { 314 if (!ret) {
313 struct seq_file *m = file->private_data; 315 struct seq_file *m = file->private_data;
314 316
315 m->private = __start_ftrace_events; 317 m->private = ftrace_events.next;
316 } 318 }
317 return ret; 319 return ret;
318} 320}
@@ -797,9 +799,17 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
797 return 0; 799 return 0;
798} 800}
799 801
802extern struct ftrace_event_call __start_ftrace_events[];
803extern struct ftrace_event_call __stop_ftrace_events[];
804
805#define for_each_event(event) \
806 for (event = __start_ftrace_events; \
807 (unsigned long)event < (unsigned long)__stop_ftrace_events; \
808 event++)
809
800static __init int event_trace_init(void) 810static __init int event_trace_init(void)
801{ 811{
802 struct ftrace_event_call *call = __start_ftrace_events; 812 struct ftrace_event_call *call;
803 struct dentry *d_tracer; 813 struct dentry *d_tracer;
804 struct dentry *entry; 814 struct dentry *entry;
805 struct dentry *d_events; 815 struct dentry *d_events;
@@ -830,6 +840,7 @@ static __init int event_trace_init(void)
830 /* The linker may leave blanks */ 840 /* The linker may leave blanks */
831 if (!call->name) 841 if (!call->name)
832 continue; 842 continue;
843 list_add(&call->list, &ftrace_events);
833 event_create_dir(call, d_events); 844 event_create_dir(call, d_events);
834 } 845 }
835 846
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index de42dad42a88..d30b06b02b4d 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -223,7 +223,7 @@ oom:
223 223
224void filter_free_subsystem_preds(struct event_subsystem *system) 224void filter_free_subsystem_preds(struct event_subsystem *system)
225{ 225{
226 struct ftrace_event_call *call = __start_ftrace_events; 226 struct ftrace_event_call *call;
227 int i; 227 int i;
228 228
229 if (system->n_preds) { 229 if (system->n_preds) {
@@ -234,7 +234,7 @@ void filter_free_subsystem_preds(struct event_subsystem *system)
234 system->n_preds = 0; 234 system->n_preds = 0;
235 } 235 }
236 236
237 events_for_each(call) { 237 list_for_each_entry(call, &ftrace_events, list) {
238 if (!call->define_fields) 238 if (!call->define_fields)
239 continue; 239 continue;
240 240
@@ -320,7 +320,7 @@ int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred)
320int filter_add_subsystem_pred(struct event_subsystem *system, 320int filter_add_subsystem_pred(struct event_subsystem *system,
321 struct filter_pred *pred) 321 struct filter_pred *pred)
322{ 322{
323 struct ftrace_event_call *call = __start_ftrace_events; 323 struct ftrace_event_call *call;
324 324
325 if (system->n_preds && !pred->compound) 325 if (system->n_preds && !pred->compound)
326 filter_free_subsystem_preds(system); 326 filter_free_subsystem_preds(system);
@@ -337,7 +337,7 @@ int filter_add_subsystem_pred(struct event_subsystem *system,
337 337
338 system->preds[system->n_preds] = pred; 338 system->preds[system->n_preds] = pred;
339 339
340 events_for_each(call) { 340 list_for_each_entry(call, &ftrace_events, list) {
341 int err; 341 int err;
342 342
343 if (!call->define_fields) 343 if (!call->define_fields)