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) | |||
2429 | return 0; | 2429 | return 0; |
2430 | } | 2430 | } |
2431 | 2431 | ||
2432 | static __init void | ||
2433 | early_enable_events(struct trace_array *tr, bool disable_first) | ||
2434 | { | ||
2435 | char *buf = bootup_event_buf; | ||
2436 | char *token; | ||
2437 | int ret; | ||
2438 | |||
2439 | while (true) { | ||
2440 | token = strsep(&buf, ","); | ||
2441 | |||
2442 | if (!token) | ||
2443 | break; | ||
2444 | if (!*token) | ||
2445 | continue; | ||
2446 | |||
2447 | /* Restarting syscalls requires that we stop them first */ | ||
2448 | if (disable_first) | ||
2449 | ftrace_set_clr_event(tr, token, 0); | ||
2450 | |||
2451 | ret = ftrace_set_clr_event(tr, token, 1); | ||
2452 | if (ret) | ||
2453 | pr_warn("Failed to enable trace event: %s\n", token); | ||
2454 | |||
2455 | /* Put back the comma to allow this to be called again */ | ||
2456 | if (buf) | ||
2457 | *(buf - 1) = ','; | ||
2458 | } | ||
2459 | } | ||
2460 | |||
2432 | static __init int event_trace_enable(void) | 2461 | static __init int event_trace_enable(void) |
2433 | { | 2462 | { |
2434 | struct trace_array *tr = top_trace_array(); | 2463 | struct trace_array *tr = top_trace_array(); |
2435 | struct ftrace_event_call **iter, *call; | 2464 | struct ftrace_event_call **iter, *call; |
2436 | char *buf = bootup_event_buf; | ||
2437 | char *token; | ||
2438 | int ret; | 2465 | int ret; |
2439 | 2466 | ||
2440 | if (!tr) | 2467 | if (!tr) |
@@ -2456,18 +2483,7 @@ static __init int event_trace_enable(void) | |||
2456 | */ | 2483 | */ |
2457 | __trace_early_add_events(tr); | 2484 | __trace_early_add_events(tr); |
2458 | 2485 | ||
2459 | while (true) { | 2486 | early_enable_events(tr, false); |
2460 | token = strsep(&buf, ","); | ||
2461 | |||
2462 | if (!token) | ||
2463 | break; | ||
2464 | if (!*token) | ||
2465 | continue; | ||
2466 | |||
2467 | ret = ftrace_set_clr_event(tr, token, 1); | ||
2468 | if (ret) | ||
2469 | pr_warn("Failed to enable trace event: %s\n", token); | ||
2470 | } | ||
2471 | 2487 | ||
2472 | trace_printk_start_comm(); | 2488 | trace_printk_start_comm(); |
2473 | 2489 | ||
@@ -2478,6 +2494,31 @@ static __init int event_trace_enable(void) | |||
2478 | return 0; | 2494 | return 0; |
2479 | } | 2495 | } |
2480 | 2496 | ||
2497 | /* | ||
2498 | * event_trace_enable() is called from trace_event_init() first to | ||
2499 | * initialize events and perhaps start any events that are on the | ||
2500 | * command line. Unfortunately, there are some events that will not | ||
2501 | * start this early, like the system call tracepoints that need | ||
2502 | * to set the TIF_SYSCALL_TRACEPOINT flag of pid 1. But event_trace_enable() | ||
2503 | * is called before pid 1 starts, and this flag is never set, making | ||
2504 | * the syscall tracepoint never get reached, but the event is enabled | ||
2505 | * regardless (and not doing anything). | ||
2506 | */ | ||
2507 | static __init int event_trace_enable_again(void) | ||
2508 | { | ||
2509 | struct trace_array *tr; | ||
2510 | |||
2511 | tr = top_trace_array(); | ||
2512 | if (!tr) | ||
2513 | return -ENODEV; | ||
2514 | |||
2515 | early_enable_events(tr, true); | ||
2516 | |||
2517 | return 0; | ||
2518 | } | ||
2519 | |||
2520 | early_initcall(event_trace_enable_again); | ||
2521 | |||
2481 | static __init int event_trace_init(void) | 2522 | static __init int event_trace_init(void) |
2482 | { | 2523 | { |
2483 | struct trace_array *tr; | 2524 | struct trace_array *tr; |