diff options
-rw-r--r-- | kernel/trace/ftrace.c | 18 |
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 | */ |
1418 | static int | 1418 | static int |
1419 | ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) | 1419 | ftrace_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 | ||
4190 | static inline int | 4200 | static inline int |
4191 | ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip) | 4201 | ftrace_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(); |