diff options
Diffstat (limited to 'kernel/trace/trace_events.c')
| -rw-r--r-- | kernel/trace/trace_events.c | 69 | 
1 files changed, 55 insertions, 14 deletions
| diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 366a78a3e61e..b03a0ea77b99 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -2429,12 +2429,39 @@ static __init int event_trace_memsetup(void)  	return 0;  } +static __init void +early_enable_events(struct trace_array *tr, bool disable_first) +{ +	char *buf = bootup_event_buf; +	char *token; +	int ret; + +	while (true) { +		token = strsep(&buf, ","); + +		if (!token) +			break; +		if (!*token) +			continue; + +		/* Restarting syscalls requires that we stop them first */ +		if (disable_first) +			ftrace_set_clr_event(tr, token, 0); + +		ret = ftrace_set_clr_event(tr, token, 1); +		if (ret) +			pr_warn("Failed to enable trace event: %s\n", token); + +		/* Put back the comma to allow this to be called again */ +		if (buf) +			*(buf - 1) = ','; +	} +} +  static __init int event_trace_enable(void)  {  	struct trace_array *tr = top_trace_array();  	struct ftrace_event_call **iter, *call; -	char *buf = bootup_event_buf; -	char *token;  	int ret;  	if (!tr) @@ -2456,18 +2483,7 @@ static __init int event_trace_enable(void)  	 */  	__trace_early_add_events(tr); -	while (true) { -		token = strsep(&buf, ","); - -		if (!token) -			break; -		if (!*token) -			continue; - -		ret = ftrace_set_clr_event(tr, token, 1); -		if (ret) -			pr_warn("Failed to enable trace event: %s\n", token); -	} +	early_enable_events(tr, false);  	trace_printk_start_comm(); @@ -2478,6 +2494,31 @@ static __init int event_trace_enable(void)  	return 0;  } +/* + * event_trace_enable() is called from trace_event_init() first to + * initialize events and perhaps start any events that are on the + * command line. Unfortunately, there are some events that will not + * start this early, like the system call tracepoints that need + * to set the TIF_SYSCALL_TRACEPOINT flag of pid 1. But event_trace_enable() + * is called before pid 1 starts, and this flag is never set, making + * the syscall tracepoint never get reached, but the event is enabled + * regardless (and not doing anything). + */ +static __init int event_trace_enable_again(void) +{ +	struct trace_array *tr; + +	tr = top_trace_array(); +	if (!tr) +		return -ENODEV; + +	early_enable_events(tr, true); + +	return 0; +} + +early_initcall(event_trace_enable_again); +  static __init int event_trace_init(void)  {  	struct trace_array *tr; | 
