History

Merge tag 'trace-v4.2-rc2-fix3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull ftrace fix from Steven Rostedt: "Back in 3.16 the ftrace code was redesigned and cleaned up to remove the double iteration list (one for registered ftrace ops, and one for registered "global" ops), to just use one list. That simplified the code but also broke the function tracing filtering on pid. This updates the code to handle the filtering again with the new logic" * tag 'trace-v4.2-rc2-fix3' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: ftrace: Fix breakage of set_ftrace_pid

Linus Torvalds committed 11 years ago

Commit 763e3262 parents 4520083 e3eea142 files · +37 −18Browse files

Unified · Split

2 files
  1. include/linux/ftrace.h +3 −0
  2. kernel/trace/ftrace.c +34 −18
include/linux/ftrace.h+3−0
@@ -116,6 +116,7 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops); · 115 unmodified lines
116 * SAVE_REGS. If another ops with this flag set is already registered116 * SAVE_REGS. If another ops with this flag set is already registered
117 * for any of the functions that this ops will be registered for, then117 * for any of the functions that this ops will be registered for, then
118 * this ops will fail to register or set_filter_ip.118 * this ops will fail to register or set_filter_ip.
119 * PID - Is affected by set_ftrace_pid (allows filtering on those pids)
119 */120 */
120enum {121enum {
121 FTRACE_OPS_FL_ENABLED = 1 << 0,122 FTRACE_OPS_FL_ENABLED = 1 << 0,
@@ -132,6 +133,7 @@ enum { · 10 unmodified lines
132 FTRACE_OPS_FL_MODIFYING = 1 << 11,133 FTRACE_OPS_FL_MODIFYING = 1 << 11,
133 FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12,134 FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12,
134 FTRACE_OPS_FL_IPMODIFY = 1 << 13,135 FTRACE_OPS_FL_IPMODIFY = 1 << 13,
136 FTRACE_OPS_FL_PID = 1 << 14,
135};137};
136 138
137#ifdef CONFIG_DYNAMIC_FTRACE139#ifdef CONFIG_DYNAMIC_FTRACE
@@ -159,6 +161,7 @@ struct ftrace_ops { · 21 unmodified lines
159 struct ftrace_ops *next;161 struct ftrace_ops *next;
160 unsigned long flags;162 unsigned long flags;
161 void *private;163 void *private;
164 ftrace_func_t saved_func;
162 int __percpu *disabled;165 int __percpu *disabled;
163#ifdef CONFIG_DYNAMIC_FTRACE166#ifdef CONFIG_DYNAMIC_FTRACE
164 int nr_trampolines;167 int nr_trampolines;
kernel/trace/ftrace.c+34−18
@@ -98,6 +98,13 @@ struct ftrace_pid { · 97 unmodified lines
98 struct pid *pid;98 struct pid *pid;
99};99};
100 100
101static bool ftrace_pids_enabled(void)
102{
103 return !list_empty(&ftrace_pids);
104}
105
106static void ftrace_update_trampoline(struct ftrace_ops *ops);
107
101/*108/*
102 * ftrace_disabled is set when an anomaly is discovered.109 * ftrace_disabled is set when an anomaly is discovered.
103 * ftrace_disabled is much stronger than ftrace_enabled.110 * ftrace_disabled is much stronger than ftrace_enabled.
@@ -109,7 +116,6 @@ static DEFINE_MUTEX(ftrace_lock); · 5 unmodified lines
109static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end;116static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end;
110static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;117static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;
111ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;118ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
112ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
113static struct ftrace_ops global_ops;119static struct ftrace_ops global_ops;
114static struct ftrace_ops control_ops;120static struct ftrace_ops control_ops;
115 121
@@ -183,14 +189,7 @@ static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip, · 67 unmodified lines
183 if (!test_tsk_trace_trace(current))189 if (!test_tsk_trace_trace(current))
184 return;190 return;
185 191
186 ftrace_pid_function(ip, parent_ip, op, regs);192 op->saved_func(ip, parent_ip, op, regs);
187}
188
189static void set_ftrace_pid_function(ftrace_func_t func)
190{
191 /* do not set ftrace_pid_function to itself! */
192 if (func != ftrace_pid_func)
193 ftrace_pid_function = func;
194}193}
195 194
196/**195/**
@@ -202,7 +201,6 @@ static void set_ftrace_pid_function(ftrace_func_t func) · 5 unmodified lines
202void clear_ftrace_function(void)201void clear_ftrace_function(void)
203{202{
204 ftrace_trace_function = ftrace_stub;203 ftrace_trace_function = ftrace_stub;
205 ftrace_pid_function = ftrace_stub;
206}204}
207 205
208static void control_ops_disable_all(struct ftrace_ops *ops)206static void control_ops_disable_all(struct ftrace_ops *ops)
@@ -436,6 +434,12 @@ static int __register_ftrace_function(struct ftrace_ops *ops) · 227 unmodified lines
436 } else434 } else
437 add_ftrace_ops(&ftrace_ops_list, ops);435 add_ftrace_ops(&ftrace_ops_list, ops);
438 436
437 /* Always save the function, and reset at unregistering */
438 ops->saved_func = ops->func;
439
440 if (ops->flags & FTRACE_OPS_FL_PID && ftrace_pids_enabled())
441 ops->func = ftrace_pid_func;
442
439 ftrace_update_trampoline(ops);443 ftrace_update_trampoline(ops);
440 444
441 if (ftrace_enabled)445 if (ftrace_enabled)
@@ -463,15 +467,28 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) · 21 unmodified lines
463 if (ftrace_enabled)467 if (ftrace_enabled)
464 update_ftrace_function();468 update_ftrace_function();
465 469
470 ops->func = ops->saved_func;
471
466 return 0;472 return 0;
467}473}
468 474
469static void ftrace_update_pid_func(void)475static void ftrace_update_pid_func(void)
470{476{
477 bool enabled = ftrace_pids_enabled();
478 struct ftrace_ops *op;
479
471 /* Only do something if we are tracing something */480 /* Only do something if we are tracing something */
472 if (ftrace_trace_function == ftrace_stub)481 if (ftrace_trace_function == ftrace_stub)
473 return;482 return;
474 483
484 do_for_each_ftrace_op(op, ftrace_ops_list) {
485 if (op->flags & FTRACE_OPS_FL_PID) {
486 op->func = enabled ? ftrace_pid_func :
487 op->saved_func;
488 ftrace_update_trampoline(op);
489 }
490 } while_for_each_ftrace_op(op);
491
475 update_ftrace_function();492 update_ftrace_function();
476}493}
477 494
@@ -1133,7 +1150,8 @@ static struct ftrace_ops global_ops = { · 655 unmodified lines
1133 .local_hash.filter_hash = EMPTY_HASH,1150 .local_hash.filter_hash = EMPTY_HASH,
1134 INIT_OPS_HASH(global_ops)1151 INIT_OPS_HASH(global_ops)
1135 .flags = FTRACE_OPS_FL_RECURSION_SAFE |1152 .flags = FTRACE_OPS_FL_RECURSION_SAFE |
1136 FTRACE_OPS_FL_INITIALIZED,1153 FTRACE_OPS_FL_INITIALIZED |
1154 FTRACE_OPS_FL_PID,
1137};1155};
1138 1156
1139/*1157/*
@@ -5023,7 +5041,9 @@ static void ftrace_update_trampoline(struct ftrace_ops *ops) · 3883 unmodified lines
5023 5041
5024static struct ftrace_ops global_ops = {5042static struct ftrace_ops global_ops = {
5025 .func = ftrace_stub,5043 .func = ftrace_stub,
5026 .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,5044 .flags = FTRACE_OPS_FL_RECURSION_SAFE |
5045 FTRACE_OPS_FL_INITIALIZED |
5046 FTRACE_OPS_FL_PID,
5027};5047};
5028 5048
5029static int __init ftrace_nodyn_init(void)5049static int __init ftrace_nodyn_init(void)
@@ -5080,11 +5100,6 @@ void ftrace_init_array_ops(struct trace_array *tr, ftrace_func_t func) · 50 unmodified lines
5080 if (WARN_ON(tr->ops->func != ftrace_stub))5100 if (WARN_ON(tr->ops->func != ftrace_stub))
5081 printk("ftrace ops had %pS for function\n",5101 printk("ftrace ops had %pS for function\n",
5082 tr->ops->func);5102 tr->ops->func);
5083 /* Only the top level instance does pid tracing */
5084 if (!list_empty(&ftrace_pids)) {
5085 set_ftrace_pid_function(func);
5086 func = ftrace_pid_func;
5087 }
5088 }5103 }
5089 tr->ops->func = func;5104 tr->ops->func = func;
5090 tr->ops->private = tr;5105 tr->ops->private = tr;
@@ -5371,7 +5386,7 @@ static void *fpid_start(struct seq_file *m, loff_t *pos) · 280 unmodified lines
5371{5386{
5372 mutex_lock(&ftrace_lock);5387 mutex_lock(&ftrace_lock);
5373 5388
5374 if (list_empty(&ftrace_pids) && (!*pos))5389 if (!ftrace_pids_enabled() && (!*pos))
5375 return (void *) 1;5390 return (void *) 1;
5376 5391
5377 return seq_list_start(&ftrace_pids, *pos);5392 return seq_list_start(&ftrace_pids, *pos);
@@ -5610,6 +5625,7 @@ static struct ftrace_ops graph_ops = { · 232 unmodified lines
5610 .func = ftrace_stub,5625 .func = ftrace_stub,
5611 .flags = FTRACE_OPS_FL_RECURSION_SAFE |5626 .flags = FTRACE_OPS_FL_RECURSION_SAFE |
5612 FTRACE_OPS_FL_INITIALIZED |5627 FTRACE_OPS_FL_INITIALIZED |
5628 FTRACE_OPS_FL_PID |
5613 FTRACE_OPS_FL_STUB,5629 FTRACE_OPS_FL_STUB,
5614#ifdef FTRACE_GRAPH_TRAMP_ADDR5630#ifdef FTRACE_GRAPH_TRAMP_ADDR
5615 .trampoline = FTRACE_GRAPH_TRAMP_ADDR,5631 .trampoline = FTRACE_GRAPH_TRAMP_ADDR,