tracing: Use class->reg() for all registering of events
Because kprobes and syscalls need special processing to register events, the class->reg() method was created to handle the differences. But instead of creating a default ->reg for perf and ftrace events, the code was scattered with: if (class->reg) class->reg(); else default_reg(); This is messy and can also lead to bugs. This patch cleans up this code and creates a default reg() entry for the events allowing for the code to directly call the class->reg() without the condition. Reported-by: Peter Zijlstra <peterz@infradead.org> Acked-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
committed by
Steven Rostedt
parent
d62f85d1e2
commit
a1d0ce8213
@@ -146,6 +146,9 @@ struct ftrace_event_class {
|
|||||||
int (*raw_init)(struct ftrace_event_call *);
|
int (*raw_init)(struct ftrace_event_call *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern int ftrace_event_reg(struct ftrace_event_call *event,
|
||||||
|
enum trace_reg type);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TRACE_EVENT_FL_ENABLED_BIT,
|
TRACE_EVENT_FL_ENABLED_BIT,
|
||||||
TRACE_EVENT_FL_FILTERED_BIT,
|
TRACE_EVENT_FL_FILTERED_BIT,
|
||||||
|
@@ -439,6 +439,7 @@ static inline notrace int ftrace_get_offsets_##call( \
|
|||||||
* .fields = LIST_HEAD_INIT(event_class_##call.fields),
|
* .fields = LIST_HEAD_INIT(event_class_##call.fields),
|
||||||
* .raw_init = trace_event_raw_init,
|
* .raw_init = trace_event_raw_init,
|
||||||
* .probe = ftrace_raw_event_##call,
|
* .probe = ftrace_raw_event_##call,
|
||||||
|
* .reg = ftrace_event_reg,
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
* static struct ftrace_event_call __used
|
* static struct ftrace_event_call __used
|
||||||
@@ -567,6 +568,7 @@ static struct ftrace_event_class __used event_class_##call = { \
|
|||||||
.fields = LIST_HEAD_INIT(event_class_##call.fields),\
|
.fields = LIST_HEAD_INIT(event_class_##call.fields),\
|
||||||
.raw_init = trace_event_raw_init, \
|
.raw_init = trace_event_raw_init, \
|
||||||
.probe = ftrace_raw_event_##call, \
|
.probe = ftrace_raw_event_##call, \
|
||||||
|
.reg = ftrace_event_reg, \
|
||||||
_TRACE_PERF_INIT(call) \
|
_TRACE_PERF_INIT(call) \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -54,13 +54,7 @@ static int perf_trace_event_init(struct ftrace_event_call *tp_event,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tp_event->class->reg)
|
|
||||||
ret = tp_event->class->reg(tp_event, TRACE_REG_PERF_REGISTER);
|
ret = tp_event->class->reg(tp_event, TRACE_REG_PERF_REGISTER);
|
||||||
else
|
|
||||||
ret = tracepoint_probe_register(tp_event->name,
|
|
||||||
tp_event->class->perf_probe,
|
|
||||||
tp_event);
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@@ -94,9 +88,7 @@ int perf_trace_init(struct perf_event *p_event)
|
|||||||
mutex_lock(&event_mutex);
|
mutex_lock(&event_mutex);
|
||||||
list_for_each_entry(tp_event, &ftrace_events, list) {
|
list_for_each_entry(tp_event, &ftrace_events, list) {
|
||||||
if (tp_event->event.type == event_id &&
|
if (tp_event->event.type == event_id &&
|
||||||
tp_event->class &&
|
tp_event->class && tp_event->class->reg &&
|
||||||
(tp_event->class->perf_probe ||
|
|
||||||
tp_event->class->reg) &&
|
|
||||||
try_module_get(tp_event->mod)) {
|
try_module_get(tp_event->mod)) {
|
||||||
ret = perf_trace_event_init(tp_event, p_event);
|
ret = perf_trace_event_init(tp_event, p_event);
|
||||||
break;
|
break;
|
||||||
@@ -136,12 +128,7 @@ void perf_trace_destroy(struct perf_event *p_event)
|
|||||||
if (--tp_event->perf_refcount > 0)
|
if (--tp_event->perf_refcount > 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (tp_event->class->reg)
|
|
||||||
tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER);
|
tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER);
|
||||||
else
|
|
||||||
tracepoint_probe_unregister(tp_event->name,
|
|
||||||
tp_event->class->perf_probe,
|
|
||||||
tp_event);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure our callback won't be called anymore. See
|
* Ensure our callback won't be called anymore. See
|
||||||
|
@@ -141,6 +141,35 @@ int trace_event_raw_init(struct ftrace_event_call *call)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(trace_event_raw_init);
|
EXPORT_SYMBOL_GPL(trace_event_raw_init);
|
||||||
|
|
||||||
|
int ftrace_event_reg(struct ftrace_event_call *call, enum trace_reg type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case TRACE_REG_REGISTER:
|
||||||
|
return tracepoint_probe_register(call->name,
|
||||||
|
call->class->probe,
|
||||||
|
call);
|
||||||
|
case TRACE_REG_UNREGISTER:
|
||||||
|
tracepoint_probe_unregister(call->name,
|
||||||
|
call->class->probe,
|
||||||
|
call);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PERF_EVENTS
|
||||||
|
case TRACE_REG_PERF_REGISTER:
|
||||||
|
return tracepoint_probe_register(call->name,
|
||||||
|
call->class->perf_probe,
|
||||||
|
call);
|
||||||
|
case TRACE_REG_PERF_UNREGISTER:
|
||||||
|
tracepoint_probe_unregister(call->name,
|
||||||
|
call->class->perf_probe,
|
||||||
|
call);
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(ftrace_event_reg);
|
||||||
|
|
||||||
static int ftrace_event_enable_disable(struct ftrace_event_call *call,
|
static int ftrace_event_enable_disable(struct ftrace_event_call *call,
|
||||||
int enable)
|
int enable)
|
||||||
{
|
{
|
||||||
@@ -151,23 +180,13 @@ static int ftrace_event_enable_disable(struct ftrace_event_call *call,
|
|||||||
if (call->flags & TRACE_EVENT_FL_ENABLED) {
|
if (call->flags & TRACE_EVENT_FL_ENABLED) {
|
||||||
call->flags &= ~TRACE_EVENT_FL_ENABLED;
|
call->flags &= ~TRACE_EVENT_FL_ENABLED;
|
||||||
tracing_stop_cmdline_record();
|
tracing_stop_cmdline_record();
|
||||||
if (call->class->reg)
|
|
||||||
call->class->reg(call, TRACE_REG_UNREGISTER);
|
call->class->reg(call, TRACE_REG_UNREGISTER);
|
||||||
else
|
|
||||||
tracepoint_probe_unregister(call->name,
|
|
||||||
call->class->probe,
|
|
||||||
call);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (!(call->flags & TRACE_EVENT_FL_ENABLED)) {
|
if (!(call->flags & TRACE_EVENT_FL_ENABLED)) {
|
||||||
tracing_start_cmdline_record();
|
tracing_start_cmdline_record();
|
||||||
if (call->class->reg)
|
|
||||||
ret = call->class->reg(call, TRACE_REG_REGISTER);
|
ret = call->class->reg(call, TRACE_REG_REGISTER);
|
||||||
else
|
|
||||||
ret = tracepoint_probe_register(call->name,
|
|
||||||
call->class->probe,
|
|
||||||
call);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
tracing_stop_cmdline_record();
|
tracing_stop_cmdline_record();
|
||||||
pr_info("event trace: Could not enable event "
|
pr_info("event trace: Could not enable event "
|
||||||
@@ -205,8 +224,7 @@ static int __ftrace_set_clr_event(const char *match, const char *sub,
|
|||||||
mutex_lock(&event_mutex);
|
mutex_lock(&event_mutex);
|
||||||
list_for_each_entry(call, &ftrace_events, list) {
|
list_for_each_entry(call, &ftrace_events, list) {
|
||||||
|
|
||||||
if (!call->name || !call->class ||
|
if (!call->name || !call->class || !call->class->reg)
|
||||||
(!call->class->probe && !call->class->reg))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (match &&
|
if (match &&
|
||||||
@@ -332,7 +350,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
|
|||||||
* The ftrace subsystem is for showing formats only.
|
* The ftrace subsystem is for showing formats only.
|
||||||
* They can not be enabled or disabled via the event files.
|
* They can not be enabled or disabled via the event files.
|
||||||
*/
|
*/
|
||||||
if (call->class && (call->class->probe || call->class->reg))
|
if (call->class && call->class->reg)
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,8 +503,7 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
|
|||||||
|
|
||||||
mutex_lock(&event_mutex);
|
mutex_lock(&event_mutex);
|
||||||
list_for_each_entry(call, &ftrace_events, list) {
|
list_for_each_entry(call, &ftrace_events, list) {
|
||||||
if (!call->name || !call->class ||
|
if (!call->name || !call->class || !call->class->reg)
|
||||||
(!call->class->probe && !call->class->reg))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (system && strcmp(call->class->system, system) != 0)
|
if (system && strcmp(call->class->system, system) != 0)
|
||||||
@@ -977,12 +994,12 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (call->class->probe || call->class->reg)
|
if (call->class->reg)
|
||||||
trace_create_file("enable", 0644, call->dir, call,
|
trace_create_file("enable", 0644, call->dir, call,
|
||||||
enable);
|
enable);
|
||||||
|
|
||||||
#ifdef CONFIG_PERF_EVENTS
|
#ifdef CONFIG_PERF_EVENTS
|
||||||
if (call->event.type && (call->class->perf_probe || call->class->reg))
|
if (call->event.type && call->class->reg)
|
||||||
trace_create_file("id", 0444, call->dir, call,
|
trace_create_file("id", 0444, call->dir, call,
|
||||||
id);
|
id);
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user