diff options
Diffstat (limited to 'kernel/trace/trace_events.c')
| -rw-r--r-- | kernel/trace/trace_events.c | 116 | 
1 files changed, 78 insertions, 38 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 29111da1d10..d608d09d08c 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1199,6 +1199,31 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,  	return 0;  } +static void event_remove(struct ftrace_event_call *call) +{ +	ftrace_event_enable_disable(call, 0); +	if (call->event.funcs) +		__unregister_ftrace_event(&call->event); +	list_del(&call->list); +} + +static int event_init(struct ftrace_event_call *call) +{ +	int ret = 0; + +	if (WARN_ON(!call->name)) +		return -EINVAL; + +	if (call->class->raw_init) { +		ret = call->class->raw_init(call); +		if (ret < 0 && ret != -ENOSYS) +			pr_warn("Could not initialize trace events/%s\n", +				call->name); +	} + +	return ret; +} +  static int  __trace_add_event_call(struct ftrace_event_call *call, struct module *mod,  		       const struct file_operations *id, @@ -1209,19 +1234,9 @@ __trace_add_event_call(struct ftrace_event_call *call, struct module *mod,  	struct dentry *d_events;  	int ret; -	/* The linker may leave blanks */ -	if (!call->name) -		return -EINVAL; - -	if (call->class->raw_init) { -		ret = call->class->raw_init(call); -		if (ret < 0) { -			if (ret != -ENOSYS) -				pr_warning("Could not initialize trace events/%s\n", -					   call->name); -			return ret; -		} -	} +	ret = event_init(call); +	if (ret < 0) +		return ret;  	d_events = event_trace_events_dir();  	if (!d_events) @@ -1272,13 +1287,10 @@ static void remove_subsystem_dir(const char *name)   */  static void __trace_remove_event_call(struct ftrace_event_call *call)  { -	ftrace_event_enable_disable(call, 0); -	if (call->event.funcs) -		__unregister_ftrace_event(&call->event); -	debugfs_remove_recursive(call->dir); -	list_del(&call->list); +	event_remove(call);  	trace_destroy_fields(call);  	destroy_preds(call); +	debugfs_remove_recursive(call->dir);  	remove_subsystem_dir(call->class->system);  } @@ -1450,15 +1462,43 @@ static __init int setup_trace_event(char *str)  }  __setup("trace_event=", setup_trace_event); +static __init int event_trace_enable(void) +{ +	struct ftrace_event_call **iter, *call; +	char *buf = bootup_event_buf; +	char *token; +	int ret; + +	for_each_event(iter, __start_ftrace_events, __stop_ftrace_events) { + +		call = *iter; +		ret = event_init(call); +		if (!ret) +			list_add(&call->list, &ftrace_events); +	} + +	while (true) { +		token = strsep(&buf, ","); + +		if (!token) +			break; +		if (!*token) +			continue; + +		ret = ftrace_set_clr_event(token, 1); +		if (ret) +			pr_warn("Failed to enable trace event: %s\n", token); +	} +	return 0; +} +  static __init int event_trace_init(void)  { -	struct ftrace_event_call **call; +	struct ftrace_event_call *call;  	struct dentry *d_tracer;  	struct dentry *entry;  	struct dentry *d_events;  	int ret; -	char *buf = bootup_event_buf; -	char *token;  	d_tracer = tracing_init_dentry();  	if (!d_tracer) @@ -1497,24 +1537,19 @@ static __init int event_trace_init(void)  	if (trace_define_common_fields())  		pr_warning("tracing: Failed to allocate common fields"); -	for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { -		__trace_add_event_call(*call, NULL, &ftrace_event_id_fops, +	/* +	 * Early initialization already enabled ftrace event. +	 * Now it's only necessary to create the event directory. +	 */ +	list_for_each_entry(call, &ftrace_events, list) { + +		ret = event_create_dir(call, d_events, +				       &ftrace_event_id_fops,  				       &ftrace_enable_fops,  				       &ftrace_event_filter_fops,  				       &ftrace_event_format_fops); -	} - -	while (true) { -		token = strsep(&buf, ","); - -		if (!token) -			break; -		if (!*token) -			continue; - -		ret = ftrace_set_clr_event(token, 1); -		if (ret) -			pr_warning("Failed to enable trace event: %s\n", token); +		if (ret < 0) +			event_remove(call);  	}  	ret = register_module_notifier(&trace_module_nb); @@ -1523,6 +1558,7 @@ static __init int event_trace_init(void)  	return 0;  } +core_initcall(event_trace_enable);  fs_initcall(event_trace_init);  #ifdef CONFIG_FTRACE_STARTUP_TEST @@ -1646,9 +1682,11 @@ static __init void event_trace_self_tests(void)  		event_test_stuff();  		ret = __ftrace_set_clr_event(NULL, system->name, NULL, 0); -		if (WARN_ON_ONCE(ret)) +		if (WARN_ON_ONCE(ret)) {  			pr_warning("error disabling system %s\n",  				   system->name); +			continue; +		}  		pr_cont("OK\n");  	} @@ -1681,7 +1719,8 @@ static __init void event_trace_self_tests(void)  static DEFINE_PER_CPU(atomic_t, ftrace_test_event_disable);  static void -function_test_events_call(unsigned long ip, unsigned long parent_ip) +function_test_events_call(unsigned long ip, unsigned long parent_ip, +			  struct ftrace_ops *op, struct pt_regs *pt_regs)  {  	struct ring_buffer_event *event;  	struct ring_buffer *buffer; @@ -1720,6 +1759,7 @@ function_test_events_call(unsigned long ip, unsigned long parent_ip)  static struct ftrace_ops trace_ops __initdata  =  {  	.func = function_test_events_call, +	.flags = FTRACE_OPS_FL_RECURSION_SAFE,  };  static __init void event_trace_self_test_with_function(void)  |