diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2015-09-29 17:31:55 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2015-09-30 04:34:54 -0400 |
commit | 41d9c0beccbb92397bea8b04a6afd1253c064a1a (patch) | |
tree | 34c1bbde8d38381cbf40b8f456db6315278f56be /kernel/trace | |
parent | 73dddbb57bb08d465dd0ecab93db0c5209e50cfe (diff) | |
download | linux-41d9c0beccbb92397bea8b04a6afd1253c064a1a.tar.gz linux-41d9c0beccbb92397bea8b04a6afd1253c064a1a.tar.bz2 linux-41d9c0beccbb92397bea8b04a6afd1253c064a1a.zip |
tracing: Always show all tracer options in the options directory
There are options that are unique to a specific tracer (like function and
function graph). Currently, these options are only visible in the options
directory when the tracer is enabled.
This has been a pain, especially for something like the func_stack_trace
option that if used inappropriately, could bring the system to a crawl. But
the only way to see it, is to enable the function tracer.
For example, if one had done:
# cd /sys/kernel/tracing
# echo __schedule > set_ftrace_filter
# echo 1 > options/func_stack_trace
# echo function > current_tracer
The __schedule call will be traced and a stack trace will also be recorded
there. Now when you were done, you may do...
# echo nop > current_tracer
# echo > set_ftrace_filter
But you forgot to disable the func_stack_trace. The only way to disable it
is to re-enable function tracing first. If you do not add a filter to
set_ftrace_filter and just do:
# echo function > current_tracer
Now you would be performing a stack trace on *every* function! On some
systems, that causes a live lock. Others may take a few minutes to fix your
mistake.
Having the func_stack_trace option visible allows you to check it and
disable it before enabling the funtion tracer.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace.c | 53 | ||||
-rw-r--r-- | kernel/trace/trace.h | 8 |
2 files changed, 27 insertions, 34 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 865f3fad9ff0..7446d4238f87 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1213,6 +1213,8 @@ static inline int run_tracer_selftest(struct tracer *type) } #endif /* CONFIG_FTRACE_STARTUP_TEST */ +static void add_tracer_options(struct trace_array *tr, struct tracer *t); + /** * register_tracer - register a tracer with the ftrace system. * @type - the plugin for the tracer @@ -1262,6 +1264,7 @@ int register_tracer(struct tracer *type) type->next = trace_types; trace_types = type; + add_tracer_options(&global_trace, type); out: tracing_selftest_running = false; @@ -4287,9 +4290,6 @@ struct trace_option_dentry; static struct trace_option_dentry * create_trace_option_files(struct trace_array *tr, struct tracer *tracer); -static void -destroy_trace_option_files(struct trace_option_dentry *topts); - /* * Used to clear out the tracer before deletion of an instance. * Must have trace_types_lock held. @@ -4307,10 +4307,8 @@ static void tracing_set_nop(struct trace_array *tr) tr->current_trace = &nop_trace; } -static void update_tracer_options(struct trace_array *tr, struct tracer *t) +static void add_tracer_options(struct trace_array *tr, struct tracer *t) { - static struct trace_option_dentry *topts; - /* Only enable if the directory has been created already. */ if (!tr->dir) return; @@ -4319,8 +4317,11 @@ static void update_tracer_options(struct trace_array *tr, struct tracer *t) if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL)) return; - destroy_trace_option_files(topts); - topts = create_trace_option_files(tr, t); + /* Ignore if they were already created */ + if (t->topts) + return; + + t->topts = create_trace_option_files(tr, t); } static int tracing_set_tracer(struct trace_array *tr, const char *buf) @@ -4389,7 +4390,6 @@ static int tracing_set_tracer(struct trace_array *tr, const char *buf) free_snapshot(tr); } #endif - update_tracer_options(tr, t); #ifdef CONFIG_TRACER_MAX_TRACE if (t->use_max_tr && !had_max_tr) { @@ -6119,13 +6119,6 @@ tracing_init_tracefs_percpu(struct trace_array *tr, long cpu) #include "trace_selftest.c" #endif -struct trace_option_dentry { - struct tracer_opt *opt; - struct tracer_flags *flags; - struct trace_array *tr; - struct dentry *entry; -}; - static ssize_t trace_options_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) @@ -6310,27 +6303,17 @@ create_trace_option_files(struct trace_array *tr, struct tracer *tracer) if (!topts) return NULL; - for (cnt = 0; opts[cnt].name; cnt++) + for (cnt = 0; opts[cnt].name; cnt++) { create_trace_option_file(tr, &topts[cnt], flags, &opts[cnt]); + WARN_ONCE(topts[cnt].entry == NULL, + "Failed to create trace option: %s", + opts[cnt].name); + } return topts; } -static void -destroy_trace_option_files(struct trace_option_dentry *topts) -{ - int cnt; - - if (!topts) - return; - - for (cnt = 0; topts[cnt].opt; cnt++) - tracefs_remove(topts[cnt].entry); - - kfree(topts); -} - static struct dentry * create_trace_option_core_file(struct trace_array *tr, const char *option, long index) @@ -6812,6 +6795,7 @@ static struct notifier_block trace_module_nb = { static __init int tracer_init_tracefs(void) { struct dentry *d_tracer; + struct tracer *t; trace_access_lock_init(); @@ -6850,9 +6834,10 @@ static __init int tracer_init_tracefs(void) create_trace_options_dir(&global_trace); - /* If the tracer was started via cmdline, create options for it here */ - if (global_trace.current_trace != &nop_trace) - update_tracer_options(&global_trace, global_trace.current_trace); + mutex_lock(&trace_types_lock); + for (t = trace_types; t; t = t->next) + add_tracer_options(&global_trace, t); + mutex_unlock(&trace_types_lock); return 0; } diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index af34e1822dad..8ed97872b65b 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -333,6 +333,13 @@ struct tracer_flags { #define TRACER_OPT(s, b) .name = #s, .bit = b +struct trace_option_dentry { + struct tracer_opt *opt; + struct tracer_flags *flags; + struct trace_array *tr; + struct dentry *entry; +}; + /** * struct tracer - a specific tracer and its callbacks to interact with tracefs * @name: the name chosen to select it on the available_tracers file @@ -387,6 +394,7 @@ struct tracer { u32 mask, int set); struct tracer *next; struct tracer_flags *flags; + struct trace_option_dentry *topts; int enabled; int ref; bool print_max; |