Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+37 -18
+3
include/linux/ftrace.h
··· 116 116 * SAVE_REGS. If another ops with this flag set is already registered 117 117 * for any of the functions that this ops will be registered for, then 118 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 */ 120 121 enum { 121 122 FTRACE_OPS_FL_ENABLED = 1 << 0, ··· 133 132 FTRACE_OPS_FL_MODIFYING = 1 << 11, 134 133 FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12, 135 134 FTRACE_OPS_FL_IPMODIFY = 1 << 13, 135 + FTRACE_OPS_FL_PID = 1 << 14, 136 136 }; 137 137 138 138 #ifdef CONFIG_DYNAMIC_FTRACE ··· 161 159 struct ftrace_ops *next; 162 160 unsigned long flags; 163 161 void *private; 162 + ftrace_func_t saved_func; 164 163 int __percpu *disabled; 165 164 #ifdef CONFIG_DYNAMIC_FTRACE 166 165 int nr_trampolines;
+34 -18
kernel/trace/ftrace.c
··· 98 98 struct pid *pid; 99 99 }; 100 100 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 + 101 108 /* 102 109 * ftrace_disabled is set when an anomaly is discovered. 103 110 * ftrace_disabled is much stronger than ftrace_enabled. ··· 116 109 static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end; 117 110 static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end; 118 111 ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; 119 - ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub; 120 112 static struct ftrace_ops global_ops; 121 113 static struct ftrace_ops control_ops; 122 114 ··· 189 183 if (!test_tsk_trace_trace(current)) 190 184 return; 191 185 192 - ftrace_pid_function(ip, parent_ip, op, regs); 193 - } 194 - 195 - static void set_ftrace_pid_function(ftrace_func_t func) 196 - { 197 - /* do not set ftrace_pid_function to itself! */ 198 - if (func != ftrace_pid_func) 199 - ftrace_pid_function = func; 186 + op->saved_func(ip, parent_ip, op, regs); 200 187 } 201 188 202 189 /** ··· 201 202 void clear_ftrace_function(void) 202 203 { 203 204 ftrace_trace_function = ftrace_stub; 204 - ftrace_pid_function = ftrace_stub; 205 205 } 206 206 207 207 static void control_ops_disable_all(struct ftrace_ops *ops) ··· 434 436 } else 435 437 add_ftrace_ops(&ftrace_ops_list, ops); 436 438 439 + /* Always save the function, and reset at unregistering */ 440 + ops->saved_func = ops->func; 441 + 442 + if (ops->flags & FTRACE_OPS_FL_PID && ftrace_pids_enabled()) 443 + ops->func = ftrace_pid_func; 444 + 437 445 ftrace_update_trampoline(ops); 438 446 439 447 if (ftrace_enabled) ··· 467 463 if (ftrace_enabled) 468 464 update_ftrace_function(); 469 465 466 + ops->func = ops->saved_func; 467 + 470 468 return 0; 471 469 } 472 470 473 471 static void ftrace_update_pid_func(void) 474 472 { 473 + bool enabled = ftrace_pids_enabled(); 474 + struct ftrace_ops *op; 475 + 475 476 /* Only do something if we are tracing something */ 476 477 if (ftrace_trace_function == ftrace_stub) 477 478 return; 479 + 480 + do_for_each_ftrace_op(op, ftrace_ops_list) { 481 + if (op->flags & FTRACE_OPS_FL_PID) { 482 + op->func = enabled ? ftrace_pid_func : 483 + op->saved_func; 484 + ftrace_update_trampoline(op); 485 + } 486 + } while_for_each_ftrace_op(op); 478 487 479 488 update_ftrace_function(); 480 489 } ··· 1150 1133 .local_hash.filter_hash = EMPTY_HASH, 1151 1134 INIT_OPS_HASH(global_ops) 1152 1135 .flags = FTRACE_OPS_FL_RECURSION_SAFE | 1153 - FTRACE_OPS_FL_INITIALIZED, 1136 + FTRACE_OPS_FL_INITIALIZED | 1137 + FTRACE_OPS_FL_PID, 1154 1138 }; 1155 1139 1156 1140 /* ··· 5041 5023 5042 5024 static struct ftrace_ops global_ops = { 5043 5025 .func = ftrace_stub, 5044 - .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, 5026 + .flags = FTRACE_OPS_FL_RECURSION_SAFE | 5027 + FTRACE_OPS_FL_INITIALIZED | 5028 + FTRACE_OPS_FL_PID, 5045 5029 }; 5046 5030 5047 5031 static int __init ftrace_nodyn_init(void) ··· 5100 5080 if (WARN_ON(tr->ops->func != ftrace_stub)) 5101 5081 printk("ftrace ops had %pS for function\n", 5102 5082 tr->ops->func); 5103 - /* Only the top level instance does pid tracing */ 5104 - if (!list_empty(&ftrace_pids)) { 5105 - set_ftrace_pid_function(func); 5106 - func = ftrace_pid_func; 5107 - } 5108 5083 } 5109 5084 tr->ops->func = func; 5110 5085 tr->ops->private = tr; ··· 5386 5371 { 5387 5372 mutex_lock(&ftrace_lock); 5388 5373 5389 - if (list_empty(&ftrace_pids) && (!*pos)) 5374 + if (!ftrace_pids_enabled() && (!*pos)) 5390 5375 return (void *) 1; 5391 5376 5392 5377 return seq_list_start(&ftrace_pids, *pos); ··· 5625 5610 .func = ftrace_stub, 5626 5611 .flags = FTRACE_OPS_FL_RECURSION_SAFE | 5627 5612 FTRACE_OPS_FL_INITIALIZED | 5613 + FTRACE_OPS_FL_PID | 5628 5614 FTRACE_OPS_FL_STUB, 5629 5615 #ifdef FTRACE_GRAPH_TRAMP_ADDR 5630 5616 .trampoline = FTRACE_GRAPH_TRAMP_ADDR,