Commit 41d9c0be authored by Steven Rostedt (Red Hat)'s avatar Steven Rostedt (Red Hat) Committed by Steven Rostedt

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: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 73dddbb5
...@@ -1213,6 +1213,8 @@ static inline int run_tracer_selftest(struct tracer *type) ...@@ -1213,6 +1213,8 @@ static inline int run_tracer_selftest(struct tracer *type)
} }
#endif /* CONFIG_FTRACE_STARTUP_TEST */ #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. * register_tracer - register a tracer with the ftrace system.
* @type - the plugin for the tracer * @type - the plugin for the tracer
...@@ -1262,6 +1264,7 @@ int register_tracer(struct tracer *type) ...@@ -1262,6 +1264,7 @@ int register_tracer(struct tracer *type)
type->next = trace_types; type->next = trace_types;
trace_types = type; trace_types = type;
add_tracer_options(&global_trace, type);
out: out:
tracing_selftest_running = false; tracing_selftest_running = false;
...@@ -4287,9 +4290,6 @@ struct trace_option_dentry; ...@@ -4287,9 +4290,6 @@ struct trace_option_dentry;
static struct trace_option_dentry * static struct trace_option_dentry *
create_trace_option_files(struct trace_array *tr, struct tracer *tracer); 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. * Used to clear out the tracer before deletion of an instance.
* Must have trace_types_lock held. * Must have trace_types_lock held.
...@@ -4307,10 +4307,8 @@ static void tracing_set_nop(struct trace_array *tr) ...@@ -4307,10 +4307,8 @@ static void tracing_set_nop(struct trace_array *tr)
tr->current_trace = &nop_trace; 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. */ /* Only enable if the directory has been created already. */
if (!tr->dir) if (!tr->dir)
return; return;
...@@ -4319,8 +4317,11 @@ static void update_tracer_options(struct trace_array *tr, struct tracer *t) ...@@ -4319,8 +4317,11 @@ static void update_tracer_options(struct trace_array *tr, struct tracer *t)
if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL)) if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL))
return; return;
destroy_trace_option_files(topts); /* Ignore if they were already created */
topts = create_trace_option_files(tr, t); if (t->topts)
return;
t->topts = create_trace_option_files(tr, t);
} }
static int tracing_set_tracer(struct trace_array *tr, const char *buf) 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) ...@@ -4389,7 +4390,6 @@ static int tracing_set_tracer(struct trace_array *tr, const char *buf)
free_snapshot(tr); free_snapshot(tr);
} }
#endif #endif
update_tracer_options(tr, t);
#ifdef CONFIG_TRACER_MAX_TRACE #ifdef CONFIG_TRACER_MAX_TRACE
if (t->use_max_tr && !had_max_tr) { if (t->use_max_tr && !had_max_tr) {
...@@ -6119,13 +6119,6 @@ tracing_init_tracefs_percpu(struct trace_array *tr, long cpu) ...@@ -6119,13 +6119,6 @@ tracing_init_tracefs_percpu(struct trace_array *tr, long cpu)
#include "trace_selftest.c" #include "trace_selftest.c"
#endif #endif
struct trace_option_dentry {
struct tracer_opt *opt;
struct tracer_flags *flags;
struct trace_array *tr;
struct dentry *entry;
};
static ssize_t static ssize_t
trace_options_read(struct file *filp, char __user *ubuf, size_t cnt, trace_options_read(struct file *filp, char __user *ubuf, size_t cnt,
loff_t *ppos) loff_t *ppos)
...@@ -6310,27 +6303,17 @@ create_trace_option_files(struct trace_array *tr, struct tracer *tracer) ...@@ -6310,27 +6303,17 @@ create_trace_option_files(struct trace_array *tr, struct tracer *tracer)
if (!topts) if (!topts)
return NULL; return NULL;
for (cnt = 0; opts[cnt].name; cnt++) for (cnt = 0; opts[cnt].name; cnt++) {
create_trace_option_file(tr, &topts[cnt], flags, create_trace_option_file(tr, &topts[cnt], flags,
&opts[cnt]); &opts[cnt]);
WARN_ONCE(topts[cnt].entry == NULL,
"Failed to create trace option: %s",
opts[cnt].name);
}
return topts; 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 * static struct dentry *
create_trace_option_core_file(struct trace_array *tr, create_trace_option_core_file(struct trace_array *tr,
const char *option, long index) const char *option, long index)
...@@ -6812,6 +6795,7 @@ static struct notifier_block trace_module_nb = { ...@@ -6812,6 +6795,7 @@ static struct notifier_block trace_module_nb = {
static __init int tracer_init_tracefs(void) static __init int tracer_init_tracefs(void)
{ {
struct dentry *d_tracer; struct dentry *d_tracer;
struct tracer *t;
trace_access_lock_init(); trace_access_lock_init();
...@@ -6850,9 +6834,10 @@ static __init int tracer_init_tracefs(void) ...@@ -6850,9 +6834,10 @@ static __init int tracer_init_tracefs(void)
create_trace_options_dir(&global_trace); create_trace_options_dir(&global_trace);
/* If the tracer was started via cmdline, create options for it here */ mutex_lock(&trace_types_lock);
if (global_trace.current_trace != &nop_trace) for (t = trace_types; t; t = t->next)
update_tracer_options(&global_trace, global_trace.current_trace); add_tracer_options(&global_trace, t);
mutex_unlock(&trace_types_lock);
return 0; return 0;
} }
......
...@@ -333,6 +333,13 @@ struct tracer_flags { ...@@ -333,6 +333,13 @@ struct tracer_flags {
#define TRACER_OPT(s, b) .name = #s, .bit = b #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 * struct tracer - a specific tracer and its callbacks to interact with tracefs
* @name: the name chosen to select it on the available_tracers file * @name: the name chosen to select it on the available_tracers file
...@@ -387,6 +394,7 @@ struct tracer { ...@@ -387,6 +394,7 @@ struct tracer {
u32 mask, int set); u32 mask, int set);
struct tracer *next; struct tracer *next;
struct tracer_flags *flags; struct tracer_flags *flags;
struct trace_option_dentry *topts;
int enabled; int enabled;
int ref; int ref;
bool print_max; bool print_max;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment