}
#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
type->next = trace_types;
trace_types = type;
+ add_tracer_options(&global_trace, type);
out:
tracing_selftest_running = false;
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.
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;
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)
free_snapshot(tr);
}
#endif
- update_tracer_options(tr, t);
#ifdef CONFIG_TRACER_MAX_TRACE
if (t->use_max_tr && !had_max_tr) {
#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)
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)
static __init int tracer_init_tracefs(void)
{
struct dentry *d_tracer;
+ struct tracer *t;
trace_access_lock_init();
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;
}