Skip to content

Commit

Permalink
tracing/events: convert event call sites to use a link list
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steven Rostedt authored and Steven Rostedt committed Apr 14, 2009
1 parent f42c85e commit a59fd60
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 38 deletions.
1 change: 1 addition & 0 deletions include/linux/ftrace_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ void trace_current_buffer_discard_commit(struct ring_buffer_event *event);
void tracing_record_cmdline(struct task_struct *tsk);

struct ftrace_event_call {
struct list_head list;
char *name;
char *system;
struct dentry *dir;
Expand Down
13 changes: 1 addition & 12 deletions kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -739,11 +739,6 @@ struct event_subsystem {
struct filter_pred **preds;
};

#define events_for_each(event) \
for (event = __start_ftrace_events; \
(unsigned long)event < (unsigned long)__stop_ftrace_events; \
event++)

struct filter_pred;

typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event);
Expand Down Expand Up @@ -785,13 +780,7 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
return 0;
}

extern struct ftrace_event_call __start_ftrace_events[];
extern struct ftrace_event_call __stop_ftrace_events[];

#define for_each_event(event) \
for (event = __start_ftrace_events; \
(unsigned long)event < (unsigned long)__stop_ftrace_events; \
event++)
extern struct list_head ftrace_events;

extern const char *__start___trace_bprintk_fmt[];
extern const char *__stop___trace_bprintk_fmt[];
Expand Down
4 changes: 2 additions & 2 deletions kernel/trace/trace_event_profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ int ftrace_profile_enable(int event_id)
{
struct ftrace_event_call *event;

for_each_event(event) {
list_for_each_entry(event, &ftrace_events, list) {
if (event->id == event_id)
return event->profile_enable(event);
}
Expand All @@ -23,7 +23,7 @@ void ftrace_profile_disable(int event_id)
{
struct ftrace_event_call *event;

for_each_event(event) {
list_for_each_entry(event, &ftrace_events, list) {
if (event->id == event_id)
return event->profile_disable(event);
}
Expand Down
51 changes: 31 additions & 20 deletions kernel/trace/trace_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

static DEFINE_MUTEX(event_mutex);

LIST_HEAD(ftrace_events);

int trace_define_field(struct ftrace_event_call *call, char *type,
char *name, int offset, int size)
{
Expand Down Expand Up @@ -54,16 +56,14 @@ int trace_define_field(struct ftrace_event_call *call, char *type,

static void ftrace_clear_events(void)
{
struct ftrace_event_call *call = (void *)__start_ftrace_events;

struct ftrace_event_call *call;

while ((unsigned long)call < (unsigned long)__stop_ftrace_events) {
list_for_each_entry(call, &ftrace_events, list) {

if (call->enabled) {
call->enabled = 0;
call->unregfunc();
}
call++;
}
}

Expand All @@ -89,7 +89,7 @@ static void ftrace_event_enable_disable(struct ftrace_event_call *call,

static int ftrace_set_clr_event(char *buf, int set)
{
struct ftrace_event_call *call = __start_ftrace_events;
struct ftrace_event_call *call;
char *event = NULL, *sub = NULL, *match;
int ret = -EINVAL;

Expand Down Expand Up @@ -118,7 +118,7 @@ static int ftrace_set_clr_event(char *buf, int set)
}

mutex_lock(&event_mutex);
for_each_event(call) {
list_for_each_entry(call, &ftrace_events, list) {

if (!call->name || !call->regfunc)
continue;
Expand Down Expand Up @@ -224,27 +224,28 @@ ftrace_event_write(struct file *file, const char __user *ubuf,
static void *
t_next(struct seq_file *m, void *v, loff_t *pos)
{
struct ftrace_event_call *call = m->private;
struct ftrace_event_call *next = call;
struct list_head *list = m->private;
struct ftrace_event_call *call;

(*pos)++;

for (;;) {
if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
if (list == &ftrace_events)
return NULL;

call = list_entry(list, struct ftrace_event_call, list);

/*
* The ftrace subsystem is for showing formats only.
* They can not be enabled or disabled via the event files.
*/
if (call->regfunc)
break;

call++;
next = call;
list = list->next;
}

m->private = ++next;
m->private = list->next;

return call;
}
Expand All @@ -257,22 +258,23 @@ static void *t_start(struct seq_file *m, loff_t *pos)
static void *
s_next(struct seq_file *m, void *v, loff_t *pos)
{
struct ftrace_event_call *call = m->private;
struct ftrace_event_call *next;
struct list_head *list = m->private;
struct ftrace_event_call *call;

(*pos)++;

retry:
if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
if (list == &ftrace_events)
return NULL;

call = list_entry(list, struct ftrace_event_call, list);

if (!call->enabled) {
call++;
list = list->next;
goto retry;
}

next = call;
m->private = ++next;
m->private = list->next;

return call;
}
Expand Down Expand Up @@ -312,7 +314,7 @@ ftrace_event_seq_open(struct inode *inode, struct file *file)
if (!ret) {
struct seq_file *m = file->private_data;

m->private = __start_ftrace_events;
m->private = ftrace_events.next;
}
return ret;
}
Expand Down Expand Up @@ -797,9 +799,17 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
return 0;
}

extern struct ftrace_event_call __start_ftrace_events[];
extern struct ftrace_event_call __stop_ftrace_events[];

#define for_each_event(event) \
for (event = __start_ftrace_events; \
(unsigned long)event < (unsigned long)__stop_ftrace_events; \
event++)

static __init int event_trace_init(void)
{
struct ftrace_event_call *call = __start_ftrace_events;
struct ftrace_event_call *call;
struct dentry *d_tracer;
struct dentry *entry;
struct dentry *d_events;
Expand Down Expand Up @@ -830,6 +840,7 @@ static __init int event_trace_init(void)
/* The linker may leave blanks */
if (!call->name)
continue;
list_add(&call->list, &ftrace_events);
event_create_dir(call, d_events);
}

Expand Down
8 changes: 4 additions & 4 deletions kernel/trace/trace_events_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ int init_preds(struct ftrace_event_call *call)

void filter_free_subsystem_preds(struct event_subsystem *system)
{
struct ftrace_event_call *call = __start_ftrace_events;
struct ftrace_event_call *call;
int i;

if (system->n_preds) {
Expand All @@ -234,7 +234,7 @@ void filter_free_subsystem_preds(struct event_subsystem *system)
system->n_preds = 0;
}

events_for_each(call) {
list_for_each_entry(call, &ftrace_events, list) {
if (!call->define_fields)
continue;

Expand Down Expand Up @@ -320,7 +320,7 @@ int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred)
int filter_add_subsystem_pred(struct event_subsystem *system,
struct filter_pred *pred)
{
struct ftrace_event_call *call = __start_ftrace_events;
struct ftrace_event_call *call;

if (system->n_preds && !pred->compound)
filter_free_subsystem_preds(system);
Expand All @@ -337,7 +337,7 @@ int filter_add_subsystem_pred(struct event_subsystem *system,

system->preds[system->n_preds] = pred;

events_for_each(call) {
list_for_each_entry(call, &ftrace_events, list) {
int err;

if (!call->define_fields)
Expand Down

0 comments on commit a59fd60

Please sign in to comment.