diff options
| -rw-r--r-- | kernel/trace/trace.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 2f8ac1f008f5..2c720c79bc60 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -53,6 +53,11 @@ unsigned long __read_mostly tracing_thresh; | |||
| 53 | */ | 53 | */ |
| 54 | static bool __read_mostly tracing_selftest_running; | 54 | static bool __read_mostly tracing_selftest_running; |
| 55 | 55 | ||
| 56 | /* | ||
| 57 | * If a tracer is running, we do not want to run SELFTEST. | ||
| 58 | */ | ||
| 59 | static bool __read_mostly tracing_selftest_disabled; | ||
| 60 | |||
| 56 | /* For tracers that don't implement custom flags */ | 61 | /* For tracers that don't implement custom flags */ |
| 57 | static struct tracer_opt dummy_tracer_opt[] = { | 62 | static struct tracer_opt dummy_tracer_opt[] = { |
| 58 | { } | 63 | { } |
| @@ -110,14 +115,19 @@ static cpumask_var_t __read_mostly tracing_buffer_mask; | |||
| 110 | */ | 115 | */ |
| 111 | int ftrace_dump_on_oops; | 116 | int ftrace_dump_on_oops; |
| 112 | 117 | ||
| 113 | static int tracing_set_tracer(char *buf); | 118 | static int tracing_set_tracer(const char *buf); |
| 119 | |||
| 120 | #define BOOTUP_TRACER_SIZE 100 | ||
| 121 | static char bootup_tracer_buf[BOOTUP_TRACER_SIZE] __initdata; | ||
| 122 | static char *default_bootup_tracer; | ||
| 114 | 123 | ||
| 115 | static int __init set_ftrace(char *str) | 124 | static int __init set_ftrace(char *str) |
| 116 | { | 125 | { |
| 117 | tracing_set_tracer(str); | 126 | strncpy(bootup_tracer_buf, str, BOOTUP_TRACER_SIZE); |
| 127 | default_bootup_tracer = bootup_tracer_buf; | ||
| 118 | return 1; | 128 | return 1; |
| 119 | } | 129 | } |
| 120 | __setup("ftrace", set_ftrace); | 130 | __setup("ftrace=", set_ftrace); |
| 121 | 131 | ||
| 122 | static int __init set_ftrace_dump_on_oops(char *str) | 132 | static int __init set_ftrace_dump_on_oops(char *str) |
| 123 | { | 133 | { |
| @@ -468,7 +478,7 @@ int register_tracer(struct tracer *type) | |||
| 468 | type->flags->opts = dummy_tracer_opt; | 478 | type->flags->opts = dummy_tracer_opt; |
| 469 | 479 | ||
| 470 | #ifdef CONFIG_FTRACE_STARTUP_TEST | 480 | #ifdef CONFIG_FTRACE_STARTUP_TEST |
| 471 | if (type->selftest) { | 481 | if (type->selftest && !tracing_selftest_disabled) { |
| 472 | struct tracer *saved_tracer = current_trace; | 482 | struct tracer *saved_tracer = current_trace; |
| 473 | struct trace_array *tr = &global_trace; | 483 | struct trace_array *tr = &global_trace; |
| 474 | int i; | 484 | int i; |
| @@ -510,8 +520,25 @@ int register_tracer(struct tracer *type) | |||
| 510 | out: | 520 | out: |
| 511 | tracing_selftest_running = false; | 521 | tracing_selftest_running = false; |
| 512 | mutex_unlock(&trace_types_lock); | 522 | mutex_unlock(&trace_types_lock); |
| 513 | lock_kernel(); | ||
| 514 | 523 | ||
| 524 | if (!ret && default_bootup_tracer) { | ||
| 525 | if (!strncmp(default_bootup_tracer, type->name, | ||
| 526 | BOOTUP_TRACER_SIZE)) { | ||
| 527 | printk(KERN_INFO "Starting tracer '%s'\n", | ||
| 528 | type->name); | ||
| 529 | /* Do we want this tracer to start on bootup? */ | ||
| 530 | tracing_set_tracer(type->name); | ||
| 531 | default_bootup_tracer = NULL; | ||
| 532 | /* disable other selftests, since this will break it. */ | ||
| 533 | tracing_selftest_disabled = 1; | ||
| 534 | #ifdef CONFIG_FTRACE_STARTUP_TEST | ||
| 535 | printk(KERN_INFO "Disabling FTRACE selftests due" | ||
| 536 | " to running tracer '%s'\n", type->name); | ||
| 537 | #endif | ||
| 538 | } | ||
| 539 | } | ||
| 540 | |||
| 541 | lock_kernel(); | ||
| 515 | return ret; | 542 | return ret; |
| 516 | } | 543 | } |
| 517 | 544 | ||
| @@ -2245,7 +2272,7 @@ tracing_set_trace_read(struct file *filp, char __user *ubuf, | |||
| 2245 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 2272 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); |
| 2246 | } | 2273 | } |
| 2247 | 2274 | ||
| 2248 | static int tracing_set_tracer(char *buf) | 2275 | static int tracing_set_tracer(const char *buf) |
| 2249 | { | 2276 | { |
| 2250 | struct trace_array *tr = &global_trace; | 2277 | struct trace_array *tr = &global_trace; |
| 2251 | struct tracer *t; | 2278 | struct tracer *t; |
| @@ -3163,5 +3190,26 @@ out_free_buffer_mask: | |||
| 3163 | out: | 3190 | out: |
| 3164 | return ret; | 3191 | return ret; |
| 3165 | } | 3192 | } |
| 3193 | |||
| 3194 | __init static int clear_boot_tracer(void) | ||
| 3195 | { | ||
| 3196 | /* | ||
| 3197 | * The default tracer at boot buffer is an init section. | ||
| 3198 | * This function is called in lateinit. If we did not | ||
| 3199 | * find the boot tracer, then clear it out, to prevent | ||
| 3200 | * later registration from accessing the buffer that is | ||
| 3201 | * about to be freed. | ||
| 3202 | */ | ||
| 3203 | if (!default_bootup_tracer) | ||
| 3204 | return 0; | ||
| 3205 | |||
| 3206 | printk(KERN_INFO "ftrace bootup tracer '%s' not registered.\n", | ||
| 3207 | default_bootup_tracer); | ||
| 3208 | default_bootup_tracer = NULL; | ||
| 3209 | |||
| 3210 | return 0; | ||
| 3211 | } | ||
| 3212 | |||
| 3166 | early_initcall(tracer_alloc_buffers); | 3213 | early_initcall(tracer_alloc_buffers); |
| 3167 | fs_initcall(tracer_init_debugfs); | 3214 | fs_initcall(tracer_init_debugfs); |
| 3215 | late_initcall(clear_boot_tracer); | ||
