tracing: Define event fields early stage

Define event fields at early stage so that boot-time tracing can
access the event fields (like per-event filter setting).

Link: https://lkml.kernel.org/r/159974152862.478751.2023768466808361350.stgit@devnote2

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
Masami Hiramatsu 2020-09-10 21:38:48 +09:00 committed by Steven Rostedt (VMware)
parent 36dadef23f
commit ac343da7bc
1 changed files with 55 additions and 37 deletions

View File

@ -2123,12 +2123,48 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
return NULL;
}
static int
event_define_fields(struct trace_event_call *call)
{
struct list_head *head;
int ret = 0;
/*
* Other events may have the same class. Only update
* the fields if they are not already defined.
*/
head = trace_get_fields(call);
if (list_empty(head)) {
struct trace_event_fields *field = call->class->fields_array;
unsigned int offset = sizeof(struct trace_entry);
for (; field->type; field++) {
if (field->type == TRACE_FUNCTION_TYPE) {
field->define_fields(call);
break;
}
offset = ALIGN(offset, field->align);
ret = trace_define_field(call, field->type, field->name,
offset, field->size,
field->is_signed, field->filter_type);
if (WARN_ON_ONCE(ret)) {
pr_err("error code is %d\n", ret);
break;
}
offset += field->size;
}
}
return ret;
}
static int
event_create_dir(struct dentry *parent, struct trace_event_file *file)
{
struct trace_event_call *call = file->event_call;
struct trace_array *tr = file->tr;
struct list_head *head;
struct dentry *d_events;
const char *name;
int ret;
@ -2162,35 +2198,10 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file)
&ftrace_event_id_fops);
#endif
/*
* Other events may have the same class. Only update
* the fields if they are not already defined.
*/
head = trace_get_fields(call);
if (list_empty(head)) {
struct trace_event_fields *field = call->class->fields_array;
unsigned int offset = sizeof(struct trace_entry);
for (; field->type; field++) {
if (field->type == TRACE_FUNCTION_TYPE) {
ret = field->define_fields(call);
break;
}
offset = ALIGN(offset, field->align);
ret = trace_define_field(call, field->type, field->name,
offset, field->size,
field->is_signed, field->filter_type);
if (ret)
break;
offset += field->size;
}
if (ret < 0) {
pr_warn("Could not initialize trace point events/%s\n",
name);
return -1;
}
ret = event_define_fields(call);
if (ret < 0) {
pr_warn("Could not initialize trace point events/%s\n", name);
return ret;
}
/*
@ -2493,7 +2504,7 @@ __trace_early_add_new_event(struct trace_event_call *call,
if (!file)
return -ENOMEM;
return 0;
return event_define_fields(call);
}
struct ftrace_module_file_ops;
@ -3431,6 +3442,18 @@ static __init int event_trace_enable_again(void)
early_initcall(event_trace_enable_again);
/* Init fields which doesn't related to the tracefs */
static __init int event_trace_init_fields(void)
{
if (trace_define_generic_fields())
pr_warn("tracing: Failed to allocated generic fields");
if (trace_define_common_fields())
pr_warn("tracing: Failed to allocate common fields");
return 0;
}
__init int event_trace_init(void)
{
struct trace_array *tr;
@ -3446,12 +3469,6 @@ __init int event_trace_init(void)
if (!entry)
pr_warn("Could not create tracefs 'available_events' entry\n");
if (trace_define_generic_fields())
pr_warn("tracing: Failed to allocated generic fields");
if (trace_define_common_fields())
pr_warn("tracing: Failed to allocate common fields");
ret = early_event_add_tracer(NULL, tr);
if (ret)
return ret;
@ -3469,6 +3486,7 @@ void __init trace_event_init(void)
event_trace_memsetup();
init_ftrace_syscalls();
event_trace_enable();
event_trace_init_fields();
}
#ifdef CONFIG_EVENT_TRACE_STARTUP_TEST