aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/ftrace.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 6c508ff33c62..13f12351b350 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1416,12 +1416,22 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
1416 * the hashes are freed with call_rcu_sched(). 1416 * the hashes are freed with call_rcu_sched().
1417 */ 1417 */
1418static int 1418static int
1419ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) 1419ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
1420{ 1420{
1421 struct ftrace_hash *filter_hash; 1421 struct ftrace_hash *filter_hash;
1422 struct ftrace_hash *notrace_hash; 1422 struct ftrace_hash *notrace_hash;
1423 int ret; 1423 int ret;
1424 1424
1425#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
1426 /*
1427 * There's a small race when adding ops that the ftrace handler
1428 * that wants regs, may be called without them. We can not
1429 * allow that handler to be called if regs is NULL.
1430 */
1431 if (regs == NULL && (ops->flags & FTRACE_OPS_FL_SAVE_REGS))
1432 return 0;
1433#endif
1434
1425 filter_hash = rcu_dereference_raw_notrace(ops->filter_hash); 1435 filter_hash = rcu_dereference_raw_notrace(ops->filter_hash);
1426 notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash); 1436 notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash);
1427 1437
@@ -4188,7 +4198,7 @@ static inline void ftrace_startup_enable(int command) { }
4188# define ftrace_shutdown_sysctl() do { } while (0) 4198# define ftrace_shutdown_sysctl() do { } while (0)
4189 4199
4190static inline int 4200static inline int
4191ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) 4201ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
4192{ 4202{
4193 return 1; 4203 return 1;
4194} 4204}
@@ -4211,7 +4221,7 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
4211 do_for_each_ftrace_op(op, ftrace_control_list) { 4221 do_for_each_ftrace_op(op, ftrace_control_list) {
4212 if (!(op->flags & FTRACE_OPS_FL_STUB) && 4222 if (!(op->flags & FTRACE_OPS_FL_STUB) &&
4213 !ftrace_function_local_disabled(op) && 4223 !ftrace_function_local_disabled(op) &&
4214 ftrace_ops_test(op, ip)) 4224 ftrace_ops_test(op, ip, regs))
4215 op->func(ip, parent_ip, op, regs); 4225 op->func(ip, parent_ip, op, regs);
4216 } while_for_each_ftrace_op(op); 4226 } while_for_each_ftrace_op(op);
4217 trace_recursion_clear(TRACE_CONTROL_BIT); 4227 trace_recursion_clear(TRACE_CONTROL_BIT);
@@ -4244,7 +4254,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
4244 */ 4254 */
4245 preempt_disable_notrace(); 4255 preempt_disable_notrace();
4246 do_for_each_ftrace_op(op, ftrace_ops_list) { 4256 do_for_each_ftrace_op(op, ftrace_ops_list) {
4247 if (ftrace_ops_test(op, ip)) 4257 if (ftrace_ops_test(op, ip, regs))
4248 op->func(ip, parent_ip, op, regs); 4258 op->func(ip, parent_ip, op, regs);
4249 } while_for_each_ftrace_op(op); 4259 } while_for_each_ftrace_op(op);
4250 preempt_enable_notrace(); 4260 preempt_enable_notrace();