tracing: Add trace options for tracer options to instances
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>
Wed, 30 Sep 2015 18:27:31 +0000 (14:27 -0400)
committerSteven Rostedt <rostedt@goodmis.org>
Wed, 30 Sep 2015 19:22:58 +0000 (15:22 -0400)
Add the tracer options to instances options directory as well. Only add the
options for tracers that are allowed to be enabled by an instance. But note,
that tracer options are global. That is, tracer options enabled in an
instance, also take affect at the top level and in other instances.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
kernel/trace/trace.c
kernel/trace/trace.h

index 7b99e36b897370d64240791a73024c706d1c8d2e..78022c1a125fba71dc0e86b0205476e6d3a4e491 100644 (file)
@@ -4308,7 +4308,7 @@ int tracing_update_buffers(void)
 
 struct trace_option_dentry;
 
-static struct trace_option_dentry *
+static void
 create_trace_option_files(struct trace_array *tr, struct tracer *tracer);
 
 /*
@@ -4334,15 +4334,7 @@ static void add_tracer_options(struct trace_array *tr, struct tracer *t)
        if (!tr->dir)
                return;
 
-       /* Currently, only the top instance has options */
-       if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL))
-               return;
-
-       /* Ignore if they were already created */
-       if (t->topts)
-               return;
-
-       t->topts = create_trace_option_files(tr, t);
+       create_trace_option_files(tr, t);
 }
 
 static int tracing_set_tracer(struct trace_array *tr, const char *buf)
@@ -6341,21 +6333,39 @@ create_trace_option_file(struct trace_array *tr,
 
 }
 
-static struct trace_option_dentry *
+static void
 create_trace_option_files(struct trace_array *tr, struct tracer *tracer)
 {
        struct trace_option_dentry *topts;
+       struct trace_options *tr_topts;
        struct tracer_flags *flags;
        struct tracer_opt *opts;
        int cnt;
+       int i;
 
        if (!tracer)
-               return NULL;
+               return;
 
        flags = tracer->flags;
 
        if (!flags || !flags->opts)
-               return NULL;
+               return;
+
+       /*
+        * If this is an instance, only create flags for tracers
+        * the instance may have.
+        */
+       if (!trace_ok_for_array(tracer, tr))
+               return;
+
+       for (i = 0; i < tr->nr_topts; i++) {
+               /*
+                * Check if these flags have already been added.
+                * Some tracers share flags.
+                */
+               if (tr->topts[i].tracer->flags == tracer->flags)
+                       return;
+       }
 
        opts = flags->opts;
 
@@ -6364,7 +6374,19 @@ create_trace_option_files(struct trace_array *tr, struct tracer *tracer)
 
        topts = kcalloc(cnt + 1, sizeof(*topts), GFP_KERNEL);
        if (!topts)
-               return NULL;
+               return;
+
+       tr_topts = krealloc(tr->topts, sizeof(*tr->topts) * (tr->nr_topts + 1),
+                           GFP_KERNEL);
+       if (!tr_topts) {
+               kfree(topts);
+               return;
+       }
+
+       tr->topts = tr_topts;
+       tr->topts[tr->nr_topts].tracer = tracer;
+       tr->topts[tr->nr_topts].topts = topts;
+       tr->nr_topts++;
 
        for (cnt = 0; opts[cnt].name; cnt++) {
                create_trace_option_file(tr, &topts[cnt], flags,
@@ -6373,8 +6395,6 @@ create_trace_option_files(struct trace_array *tr, struct tracer *tracer)
                          "Failed to create trace option: %s",
                          opts[cnt].name);
        }
-
-       return topts;
 }
 
 static struct dentry *
@@ -6552,6 +6572,21 @@ static void init_trace_flags_index(struct trace_array *tr)
                tr->trace_flags_index[i] = i;
 }
 
+static void __update_tracer_options(struct trace_array *tr)
+{
+       struct tracer *t;
+
+       for (t = trace_types; t; t = t->next)
+               add_tracer_options(tr, t);
+}
+
+static void update_tracer_options(struct trace_array *tr)
+{
+       mutex_lock(&trace_types_lock);
+       __update_tracer_options(tr);
+       mutex_unlock(&trace_types_lock);
+}
+
 static int instance_mkdir(const char *name)
 {
        struct trace_array *tr;
@@ -6605,6 +6640,7 @@ static int instance_mkdir(const char *name)
 
        init_tracer_tracefs(tr, tr->dir);
        init_trace_flags_index(tr);
+       __update_tracer_options(tr);
 
        list_add(&tr->list, &ftrace_trace_arrays);
 
@@ -6630,6 +6666,7 @@ static int instance_rmdir(const char *name)
        struct trace_array *tr;
        int found = 0;
        int ret;
+       int i;
 
        mutex_lock(&trace_types_lock);
 
@@ -6655,6 +6692,11 @@ static int instance_rmdir(const char *name)
        debugfs_remove_recursive(tr->dir);
        free_trace_buffers(tr);
 
+       for (i = 0; i < tr->nr_topts; i++) {
+               kfree(tr->topts[i].topts);
+       }
+       kfree(tr->topts);
+
        kfree(tr->name);
        kfree(tr);
 
@@ -6877,7 +6919,6 @@ 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();
 
@@ -6914,10 +6955,7 @@ static __init int tracer_init_tracefs(void)
 
        create_trace_instances(d_tracer);
 
-       mutex_lock(&trace_types_lock);
-       for (t = trace_types; t; t = t->next)
-               add_tracer_options(&global_trace, t);
-       mutex_unlock(&trace_types_lock);
+       update_tracer_options(&global_trace);
 
        return 0;
 }
index 423cb48a1d6d2d689f367a0a11695d56f0cd8f75..fb8a61c710ea53facf8b185cdc5acdb285aedbcb 100644 (file)
@@ -159,6 +159,7 @@ struct trace_array_cpu {
 };
 
 struct tracer;
+struct trace_option_dentry;
 
 struct trace_buffer {
        struct trace_array              *tr;
@@ -170,6 +171,11 @@ struct trace_buffer {
 
 #define TRACE_FLAGS_MAX_SIZE           32
 
+struct trace_options {
+       struct tracer                   *tracer;
+       struct trace_option_dentry      *topts;
+};
+
 /*
  * The trace array - an array of per-CPU trace arrays. This is the
  * highest level data structure that individual tracers deal with.
@@ -218,6 +224,7 @@ struct trace_array {
 #endif
        int                     stop_count;
        int                     clock_id;
+       int                     nr_topts;
        struct tracer           *current_trace;
        unsigned int            trace_flags;
        unsigned char           trace_flags_index[TRACE_FLAGS_MAX_SIZE];
@@ -227,6 +234,7 @@ struct trace_array {
        struct dentry           *options;
        struct dentry           *percpu_dir;
        struct dentry           *event_dir;
+       struct trace_options    *topts;
        struct list_head        systems;
        struct list_head        events;
        cpumask_var_t           tracing_cpumask; /* only trace on set CPUs */
@@ -398,7 +406,6 @@ 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;