diff options
Diffstat (limited to 'kernel/trace/trace.c')
| -rw-r--r-- | kernel/trace/trace.c | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 152d0969adf8..bbdfaa2cbdb9 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 | { |
| @@ -469,7 +479,7 @@ int register_tracer(struct tracer *type) | |||
| 469 | type->flags->opts = dummy_tracer_opt; | 479 | type->flags->opts = dummy_tracer_opt; |
| 470 | 480 | ||
| 471 | #ifdef CONFIG_FTRACE_STARTUP_TEST | 481 | #ifdef CONFIG_FTRACE_STARTUP_TEST |
| 472 | if (type->selftest) { | 482 | if (type->selftest && !tracing_selftest_disabled) { |
| 473 | struct tracer *saved_tracer = current_trace; | 483 | struct tracer *saved_tracer = current_trace; |
| 474 | struct trace_array *tr = &global_trace; | 484 | struct trace_array *tr = &global_trace; |
| 475 | int i; | 485 | int i; |
| @@ -511,8 +521,25 @@ int register_tracer(struct tracer *type) | |||
| 511 | out: | 521 | out: |
| 512 | tracing_selftest_running = false; | 522 | tracing_selftest_running = false; |
| 513 | mutex_unlock(&trace_types_lock); | 523 | mutex_unlock(&trace_types_lock); |
| 514 | lock_kernel(); | ||
| 515 | 524 | ||
| 525 | if (!ret && default_bootup_tracer) { | ||
| 526 | if (!strncmp(default_bootup_tracer, type->name, | ||
| 527 | BOOTUP_TRACER_SIZE)) { | ||
| 528 | printk(KERN_INFO "Starting tracer '%s'\n", | ||
| 529 | type->name); | ||
| 530 | /* Do we want this tracer to start on bootup? */ | ||
| 531 | tracing_set_tracer(type->name); | ||
| 532 | default_bootup_tracer = NULL; | ||
| 533 | /* disable other selftests, since this will break it. */ | ||
| 534 | tracing_selftest_disabled = 1; | ||
| 535 | #ifdef CONFIG_FTRACE_STARTUP_TEST | ||
| 536 | printk(KERN_INFO "Disabling FTRACE selftests due" | ||
| 537 | " to running tracer '%s'\n", type->name); | ||
| 538 | #endif | ||
| 539 | } | ||
| 540 | } | ||
| 541 | |||
| 542 | lock_kernel(); | ||
| 516 | return ret; | 543 | return ret; |
| 517 | } | 544 | } |
| 518 | 545 | ||
| @@ -2166,7 +2193,7 @@ tracing_set_trace_read(struct file *filp, char __user *ubuf, | |||
| 2166 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 2193 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); |
| 2167 | } | 2194 | } |
| 2168 | 2195 | ||
| 2169 | static int tracing_set_tracer(char *buf) | 2196 | static int tracing_set_tracer(const char *buf) |
| 2170 | { | 2197 | { |
| 2171 | struct trace_array *tr = &global_trace; | 2198 | struct trace_array *tr = &global_trace; |
| 2172 | struct tracer *t; | 2199 | struct tracer *t; |
| @@ -3061,12 +3088,9 @@ __init static int tracer_alloc_buffers(void) | |||
| 3061 | trace_init_cmdlines(); | 3088 | trace_init_cmdlines(); |
| 3062 | 3089 | ||
| 3063 | register_tracer(&nop_trace); | 3090 | register_tracer(&nop_trace); |
| 3091 | current_trace = &nop_trace; | ||
| 3064 | #ifdef CONFIG_BOOT_TRACER | 3092 | #ifdef CONFIG_BOOT_TRACER |
| 3065 | register_tracer(&boot_tracer); | 3093 | register_tracer(&boot_tracer); |
| 3066 | current_trace = &boot_tracer; | ||
| 3067 | current_trace->init(&global_trace); | ||
| 3068 | #else | ||
| 3069 | current_trace = &nop_trace; | ||
| 3070 | #endif | 3094 | #endif |
| 3071 | /* All seems OK, enable tracing */ | 3095 | /* All seems OK, enable tracing */ |
| 3072 | tracing_disabled = 0; | 3096 | tracing_disabled = 0; |
| @@ -3084,5 +3108,26 @@ out_free_buffer_mask: | |||
| 3084 | out: | 3108 | out: |
| 3085 | return ret; | 3109 | return ret; |
| 3086 | } | 3110 | } |
| 3111 | |||
| 3112 | __init static int clear_boot_tracer(void) | ||
| 3113 | { | ||
| 3114 | /* | ||
| 3115 | * The default tracer at boot buffer is an init section. | ||
| 3116 | * This function is called in lateinit. If we did not | ||
| 3117 | * find the boot tracer, then clear it out, to prevent | ||
| 3118 | * later registration from accessing the buffer that is | ||
| 3119 | * about to be freed. | ||
| 3120 | */ | ||
| 3121 | if (!default_bootup_tracer) | ||
| 3122 | return 0; | ||
| 3123 | |||
| 3124 | printk(KERN_INFO "ftrace bootup tracer '%s' not registered.\n", | ||
| 3125 | default_bootup_tracer); | ||
| 3126 | default_bootup_tracer = NULL; | ||
| 3127 | |||
| 3128 | return 0; | ||
| 3129 | } | ||
| 3130 | |||
| 3087 | early_initcall(tracer_alloc_buffers); | 3131 | early_initcall(tracer_alloc_buffers); |
| 3088 | fs_initcall(tracer_init_debugfs); | 3132 | fs_initcall(tracer_init_debugfs); |
| 3133 | late_initcall(clear_boot_tracer); | ||
