aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorChunyu Hu <chuhu@redhat.com>2016-03-08 08:37:01 -0500
committerSteven Rostedt <rostedt@goodmis.org>2016-03-08 11:19:08 -0500
commitd39cdd2036a63eef17a14efbd969405ca5612886 (patch)
tree547098658fa6d9e6dba8ffe73ccd756ba5638668 /kernel
parentf6cede5b49e822ebc41a099fe41ab4989f64e2cb (diff)
tracing: Make tracer_flags use the right set_flag callback
When I was updating the ftrace_stress test of ltp. I encountered a strange phenomemon, excute following steps: echo nop > /sys/kernel/debug/tracing/current_tracer echo 0 > /sys/kernel/debug/tracing/options/funcgraph-cpu bash: echo: write error: Invalid argument check dmesg: [ 1024.903855] nop_test_refuse flag set to 0: we refuse.Now cat trace_options to see the result The reason is that the trace option test will randomly setup trace option under tracing/options no matter what the current_tracer is. but the set_tracer_option is always using the set_flag callback from the current_tracer. This patch adds a pointer to tracer_flags and make it point to the tracer it belongs to. When the option is setup, the set_flag of the right tracer will be used no matter what the the current_tracer is. And the old dummy_tracer_flags is used for all the tracers which doesn't have a tracer_flags, having issue to use it to save the pointer of a tracer. So remove it and use dynamic dummy tracer_flags for tracers needing a dummy tracer_flags, as a result, there are no tracers sharing tracer_flags, so remove the check code. And save the current tracer to trace_option_dentry seems not good as it may waste mem space when mount the debug/trace fs more than one time. Link: http://lkml.kernel.org/r/1457444222-8654-1-git-send-email-chuhu@redhat.com Signed-off-by: Chunyu Hu <chuhu@redhat.com> [ Fixed up function tracer options to work with the change ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.c28
-rw-r--r--kernel/trace/trace.h1
-rw-r--r--kernel/trace/trace_functions.c6
3 files changed, 21 insertions, 14 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d9293402ee68..b401a1892dc6 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -74,11 +74,6 @@ static struct tracer_opt dummy_tracer_opt[] = {
74 { } 74 { }
75}; 75};
76 76
77static struct tracer_flags dummy_tracer_flags = {
78 .val = 0,
79 .opts = dummy_tracer_opt
80};
81
82static int 77static int
83dummy_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set) 78dummy_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
84{ 79{
@@ -1258,12 +1253,20 @@ int __init register_tracer(struct tracer *type)
1258 1253
1259 if (!type->set_flag) 1254 if (!type->set_flag)
1260 type->set_flag = &dummy_set_flag; 1255 type->set_flag = &dummy_set_flag;
1261 if (!type->flags) 1256 if (!type->flags) {
1262 type->flags = &dummy_tracer_flags; 1257 /*allocate a dummy tracer_flags*/
1263 else 1258 type->flags = kmalloc(sizeof(*type->flags), GFP_KERNEL);
1259 if (!type->flags)
1260 return -ENOMEM;
1261 type->flags->val = 0;
1262 type->flags->opts = dummy_tracer_opt;
1263 } else
1264 if (!type->flags->opts) 1264 if (!type->flags->opts)
1265 type->flags->opts = dummy_tracer_opt; 1265 type->flags->opts = dummy_tracer_opt;
1266 1266
1267 /* store the tracer for __set_tracer_option */
1268 type->flags->trace = type;
1269
1267 ret = run_tracer_selftest(type); 1270 ret = run_tracer_selftest(type);
1268 if (ret < 0) 1271 if (ret < 0)
1269 goto out; 1272 goto out;
@@ -3505,7 +3508,7 @@ static int __set_tracer_option(struct trace_array *tr,
3505 struct tracer_flags *tracer_flags, 3508 struct tracer_flags *tracer_flags,
3506 struct tracer_opt *opts, int neg) 3509 struct tracer_opt *opts, int neg)
3507{ 3510{
3508 struct tracer *trace = tr->current_trace; 3511 struct tracer *trace = tracer_flags->trace;
3509 int ret; 3512 int ret;
3510 3513
3511 ret = trace->set_flag(tr, tracer_flags->val, opts->bit, !neg); 3514 ret = trace->set_flag(tr, tracer_flags->val, opts->bit, !neg);
@@ -6391,11 +6394,8 @@ create_trace_option_files(struct trace_array *tr, struct tracer *tracer)
6391 return; 6394 return;
6392 6395
6393 for (i = 0; i < tr->nr_topts; i++) { 6396 for (i = 0; i < tr->nr_topts; i++) {
6394 /* 6397 /* Make sure there's no duplicate flags. */
6395 * Check if these flags have already been added. 6398 if (WARN_ON_ONCE(tr->topts[i].tracer->flags == tracer->flags))
6396 * Some tracers share flags.
6397 */
6398 if (tr->topts[i].tracer->flags == tracer->flags)
6399 return; 6399 return;
6400 } 6400 }
6401 6401
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 8414fa40bf27..b4cae47f283e 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -345,6 +345,7 @@ struct tracer_opt {
345struct tracer_flags { 345struct tracer_flags {
346 u32 val; 346 u32 val;
347 struct tracer_opt *opts; 347 struct tracer_opt *opts;
348 struct tracer *trace;
348}; 349};
349 350
350/* Makes more easy to define a tracer opt */ 351/* Makes more easy to define a tracer opt */
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index fcd41a166405..5a095c2e4b69 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -219,6 +219,8 @@ static void tracing_stop_function_trace(struct trace_array *tr)
219 unregister_ftrace_function(tr->ops); 219 unregister_ftrace_function(tr->ops);
220} 220}
221 221
222static struct tracer function_trace;
223
222static int 224static int
223func_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set) 225func_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
224{ 226{
@@ -228,6 +230,10 @@ func_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
228 if (!!set == !!(func_flags.val & TRACE_FUNC_OPT_STACK)) 230 if (!!set == !!(func_flags.val & TRACE_FUNC_OPT_STACK))
229 break; 231 break;
230 232
233 /* We can change this flag when not running. */
234 if (tr->current_trace != &function_trace)
235 break;
236
231 unregister_ftrace_function(tr->ops); 237 unregister_ftrace_function(tr->ops);
232 238
233 if (set) { 239 if (set) {