Skip to content

Commit 763e326

Browse files
committed
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
2 parents 4520083 + e3eea14 commit 763e326

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

include/linux/ftrace.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);
116116
* SAVE_REGS. If another ops with this flag set is already registered
117117
* for any of the functions that this ops will be registered for, then
118118
* this ops will fail to register or set_filter_ip.
119+
* PID - Is affected by set_ftrace_pid (allows filtering on those pids)
119120
*/
120121
enum {
121122
FTRACE_OPS_FL_ENABLED = 1 << 0,
@@ -132,6 +133,7 @@ enum {
132133
FTRACE_OPS_FL_MODIFYING = 1 << 11,
133134
FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12,
134135
FTRACE_OPS_FL_IPMODIFY = 1 << 13,
136+
FTRACE_OPS_FL_PID = 1 << 14,
135137
};
136138

137139
#ifdef CONFIG_DYNAMIC_FTRACE
@@ -159,6 +161,7 @@ struct ftrace_ops {
159161
struct ftrace_ops *next;
160162
unsigned long flags;
161163
void *private;
164+
ftrace_func_t saved_func;
162165
int __percpu *disabled;
163166
#ifdef CONFIG_DYNAMIC_FTRACE
164167
int nr_trampolines;

kernel/trace/ftrace.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ struct ftrace_pid {
9898
struct pid *pid;
9999
};
100100

101+
static bool ftrace_pids_enabled(void)
102+
{
103+
return !list_empty(&ftrace_pids);
104+
}
105+
106+
static void ftrace_update_trampoline(struct ftrace_ops *ops);
107+
101108
/*
102109
* ftrace_disabled is set when an anomaly is discovered.
103110
* ftrace_disabled is much stronger than ftrace_enabled.
@@ -109,7 +116,6 @@ static DEFINE_MUTEX(ftrace_lock);
109116
static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end;
110117
static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;
111118
ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
112-
ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
113119
static struct ftrace_ops global_ops;
114120
static struct ftrace_ops control_ops;
115121

@@ -183,14 +189,7 @@ static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip,
183189
if (!test_tsk_trace_trace(current))
184190
return;
185191

186-
ftrace_pid_function(ip, parent_ip, op, regs);
187-
}
188-
189-
static 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;
192+
op->saved_func(ip, parent_ip, op, regs);
194193
}
195194

196195
/**
@@ -202,7 +201,6 @@ static void set_ftrace_pid_function(ftrace_func_t func)
202201
void clear_ftrace_function(void)
203202
{
204203
ftrace_trace_function = ftrace_stub;
205-
ftrace_pid_function = ftrace_stub;
206204
}
207205

208206
static void control_ops_disable_all(struct ftrace_ops *ops)
@@ -436,6 +434,12 @@ static int __register_ftrace_function(struct ftrace_ops *ops)
436434
} else
437435
add_ftrace_ops(&ftrace_ops_list, ops);
438436

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+
439443
ftrace_update_trampoline(ops);
440444

441445
if (ftrace_enabled)
@@ -463,15 +467,28 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
463467
if (ftrace_enabled)
464468
update_ftrace_function();
465469

470+
ops->func = ops->saved_func;
471+
466472
return 0;
467473
}
468474

469475
static void ftrace_update_pid_func(void)
470476
{
477+
bool enabled = ftrace_pids_enabled();
478+
struct ftrace_ops *op;
479+
471480
/* Only do something if we are tracing something */
472481
if (ftrace_trace_function == ftrace_stub)
473482
return;
474483

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+
475492
update_ftrace_function();
476493
}
477494

@@ -1133,7 +1150,8 @@ static struct ftrace_ops global_ops = {
11331150
.local_hash.filter_hash = EMPTY_HASH,
11341151
INIT_OPS_HASH(global_ops)
11351152
.flags = FTRACE_OPS_FL_RECURSION_SAFE |
1136-
FTRACE_OPS_FL_INITIALIZED,
1153+
FTRACE_OPS_FL_INITIALIZED |
1154+
FTRACE_OPS_FL_PID,
11371155
};
11381156

11391157
/*
@@ -5023,7 +5041,9 @@ static void ftrace_update_trampoline(struct ftrace_ops *ops)
50235041

50245042
static struct ftrace_ops global_ops = {
50255043
.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,
50275047
};
50285048

50295049
static int __init ftrace_nodyn_init(void)
@@ -5080,11 +5100,6 @@ void ftrace_init_array_ops(struct trace_array *tr, ftrace_func_t func)
50805100
if (WARN_ON(tr->ops->func != ftrace_stub))
50815101
printk("ftrace ops had %pS for function\n",
50825102
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-
}
50885103
}
50895104
tr->ops->func = func;
50905105
tr->ops->private = tr;
@@ -5371,7 +5386,7 @@ static void *fpid_start(struct seq_file *m, loff_t *pos)
53715386
{
53725387
mutex_lock(&ftrace_lock);
53735388

5374-
if (list_empty(&ftrace_pids) && (!*pos))
5389+
if (!ftrace_pids_enabled() && (!*pos))
53755390
return (void *) 1;
53765391

53775392
return seq_list_start(&ftrace_pids, *pos);
@@ -5610,6 +5625,7 @@ static struct ftrace_ops graph_ops = {
56105625
.func = ftrace_stub,
56115626
.flags = FTRACE_OPS_FL_RECURSION_SAFE |
56125627
FTRACE_OPS_FL_INITIALIZED |
5628+
FTRACE_OPS_FL_PID |
56135629
FTRACE_OPS_FL_STUB,
56145630
#ifdef FTRACE_GRAPH_TRAMP_ADDR
56155631
.trampoline = FTRACE_GRAPH_TRAMP_ADDR,

0 commit comments

Comments
 (0)