{ }
 };
 
-static struct tracer_flags dummy_tracer_flags = {
-       .val = 0,
-       .opts = dummy_tracer_opt
-};
-
 static int
 dummy_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
 {
 
        if (!type->set_flag)
                type->set_flag = &dummy_set_flag;
-       if (!type->flags)
-               type->flags = &dummy_tracer_flags;
-       else
+       if (!type->flags) {
+               /*allocate a dummy tracer_flags*/
+               type->flags = kmalloc(sizeof(*type->flags), GFP_KERNEL);
+               if (!type->flags)
+                       return -ENOMEM;
+               type->flags->val = 0;
+               type->flags->opts = dummy_tracer_opt;
+       } else
                if (!type->flags->opts)
                        type->flags->opts = dummy_tracer_opt;
 
+       /* store the tracer for __set_tracer_option */
+       type->flags->trace = type;
+
        ret = run_tracer_selftest(type);
        if (ret < 0)
                goto out;
                               struct tracer_flags *tracer_flags,
                               struct tracer_opt *opts, int neg)
 {
-       struct tracer *trace = tr->current_trace;
+       struct tracer *trace = tracer_flags->trace;
        int ret;
 
        ret = trace->set_flag(tr, tracer_flags->val, opts->bit, !neg);
                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)
+               /* Make sure there's no duplicate flags. */
+               if (WARN_ON_ONCE(tr->topts[i].tracer->flags == tracer->flags))
                        return;
        }
 
 
        unregister_ftrace_function(tr->ops);
 }
 
+static struct tracer function_trace;
+
 static int
 func_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
 {
                if (!!set == !!(func_flags.val & TRACE_FUNC_OPT_STACK))
                        break;
 
+               /* We can change this flag when not running. */
+               if (tr->current_trace != &function_trace)
+                       break;
+
                unregister_ftrace_function(tr->ops);
 
                if (set) {