diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-21 02:39:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-21 02:39:03 -0400 |
commit | 56f410cf45a1c1f68f77741990e0435b06a07676 (patch) | |
tree | b52f55cd45228474818b5409b722255a0a24ed24 | |
parent | 894e21642dde19184f059c485c49abd7ecdd6ec9 (diff) | |
parent | a33d7d94eed92b23fbbc7b0de06a41b2bbaa49e3 (diff) |
Merge tag 'trace-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing fixes from Steven Rostedt:
- Fix a bug caused by not cleaning up the new instance unique triggers
when deleting an instance. It also creates a selftest that triggers
that bug.
- Fix the delayed optimization happening after kprobes boot up self
tests being removed by freeing of init memory.
- Comment kprobes on why the delay optimization is not a problem for
removal of modules, to keep other developers from searching that
riddle.
- Fix another case of rcu not watching in stack trace tracing.
* tag 'trace-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
tracing: Make sure RCU is watching before calling a stack trace
kprobes: Document how optimized kprobes are removed from module unload
selftests/ftrace: Add test to remove instance with active event triggers
selftests/ftrace: Fix bashisms
ftrace: Remove #ifdef from code and add clear_ftrace_function_probes() stub
ftrace/instances: Clear function triggers when removing instances
ftrace: Simplify glob handling in unregister_ftrace_function_probe_func()
tracing/kprobes: Enforce kprobes teardown after testing
tracing: Move postpone selftests to core from early_initcall
-rw-r--r-- | include/linux/kprobes.h | 3 | ||||
-rw-r--r-- | kernel/kprobes.c | 8 | ||||
-rw-r--r-- | kernel/trace/ftrace.c | 12 | ||||
-rw-r--r-- | kernel/trace/trace.c | 34 | ||||
-rw-r--r-- | kernel/trace/trace.h | 5 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 5 | ||||
-rwxr-xr-x | tools/testing/selftests/ftrace/ftracetest | 2 | ||||
-rw-r--r-- | tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc | 2 | ||||
-rw-r--r-- | tools/testing/selftests/ftrace/test.d/functions | 4 | ||||
-rw-r--r-- | tools/testing/selftests/ftrace/test.d/instances/instance-event.tc | 8 |
10 files changed, 72 insertions, 11 deletions
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 30f90c1a0aaf..541df0b5b815 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h | |||
@@ -349,6 +349,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table, | |||
349 | int write, void __user *buffer, | 349 | int write, void __user *buffer, |
350 | size_t *length, loff_t *ppos); | 350 | size_t *length, loff_t *ppos); |
351 | #endif | 351 | #endif |
352 | extern void wait_for_kprobe_optimizer(void); | ||
353 | #else | ||
354 | static inline void wait_for_kprobe_optimizer(void) { } | ||
352 | #endif /* CONFIG_OPTPROBES */ | 355 | #endif /* CONFIG_OPTPROBES */ |
353 | #ifdef CONFIG_KPROBES_ON_FTRACE | 356 | #ifdef CONFIG_KPROBES_ON_FTRACE |
354 | extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, | 357 | extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 7367e0ec6f81..2d2d3a568e4e 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -595,7 +595,7 @@ static void kprobe_optimizer(struct work_struct *work) | |||
595 | } | 595 | } |
596 | 596 | ||
597 | /* Wait for completing optimization and unoptimization */ | 597 | /* Wait for completing optimization and unoptimization */ |
598 | static void wait_for_kprobe_optimizer(void) | 598 | void wait_for_kprobe_optimizer(void) |
599 | { | 599 | { |
600 | mutex_lock(&kprobe_mutex); | 600 | mutex_lock(&kprobe_mutex); |
601 | 601 | ||
@@ -2183,6 +2183,12 @@ static int kprobes_module_callback(struct notifier_block *nb, | |||
2183 | * The vaddr this probe is installed will soon | 2183 | * The vaddr this probe is installed will soon |
2184 | * be vfreed buy not synced to disk. Hence, | 2184 | * be vfreed buy not synced to disk. Hence, |
2185 | * disarming the breakpoint isn't needed. | 2185 | * disarming the breakpoint isn't needed. |
2186 | * | ||
2187 | * Note, this will also move any optimized probes | ||
2188 | * that are pending to be removed from their | ||
2189 | * corresponding lists to the freeing_list and | ||
2190 | * will not be touched by the delayed | ||
2191 | * kprobe_optimizer work handler. | ||
2186 | */ | 2192 | */ |
2187 | kill_kprobe(p); | 2193 | kill_kprobe(p); |
2188 | } | 2194 | } |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 39dca4e86a94..74fdfe9ed3db 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -4144,9 +4144,9 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, | |||
4144 | int i, ret = -ENODEV; | 4144 | int i, ret = -ENODEV; |
4145 | int size; | 4145 | int size; |
4146 | 4146 | ||
4147 | if (glob && (strcmp(glob, "*") == 0 || !strlen(glob))) | 4147 | if (!glob || !strlen(glob) || !strcmp(glob, "*")) |
4148 | func_g.search = NULL; | 4148 | func_g.search = NULL; |
4149 | else if (glob) { | 4149 | else { |
4150 | int not; | 4150 | int not; |
4151 | 4151 | ||
4152 | func_g.type = filter_parse_regex(glob, strlen(glob), | 4152 | func_g.type = filter_parse_regex(glob, strlen(glob), |
@@ -4256,6 +4256,14 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, | |||
4256 | return ret; | 4256 | return ret; |
4257 | } | 4257 | } |
4258 | 4258 | ||
4259 | void clear_ftrace_function_probes(struct trace_array *tr) | ||
4260 | { | ||
4261 | struct ftrace_func_probe *probe, *n; | ||
4262 | |||
4263 | list_for_each_entry_safe(probe, n, &tr->func_probes, list) | ||
4264 | unregister_ftrace_function_probe_func(NULL, tr, probe->probe_ops); | ||
4265 | } | ||
4266 | |||
4259 | static LIST_HEAD(ftrace_commands); | 4267 | static LIST_HEAD(ftrace_commands); |
4260 | static DEFINE_MUTEX(ftrace_cmd_mutex); | 4268 | static DEFINE_MUTEX(ftrace_cmd_mutex); |
4261 | 4269 | ||
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c4536c449021..1122f151466f 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -1558,7 +1558,7 @@ static __init int init_trace_selftests(void) | |||
1558 | 1558 | ||
1559 | return 0; | 1559 | return 0; |
1560 | } | 1560 | } |
1561 | early_initcall(init_trace_selftests); | 1561 | core_initcall(init_trace_selftests); |
1562 | #else | 1562 | #else |
1563 | static inline int run_tracer_selftest(struct tracer *type) | 1563 | static inline int run_tracer_selftest(struct tracer *type) |
1564 | { | 1564 | { |
@@ -2568,7 +2568,36 @@ static inline void ftrace_trace_stack(struct trace_array *tr, | |||
2568 | void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, | 2568 | void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, |
2569 | int pc) | 2569 | int pc) |
2570 | { | 2570 | { |
2571 | __ftrace_trace_stack(tr->trace_buffer.buffer, flags, skip, pc, NULL); | 2571 | struct ring_buffer *buffer = tr->trace_buffer.buffer; |
2572 | |||
2573 | if (rcu_is_watching()) { | ||
2574 | __ftrace_trace_stack(buffer, flags, skip, pc, NULL); | ||
2575 | return; | ||
2576 | } | ||
2577 | |||
2578 | /* | ||
2579 | * When an NMI triggers, RCU is enabled via rcu_nmi_enter(), | ||
2580 | * but if the above rcu_is_watching() failed, then the NMI | ||
2581 | * triggered someplace critical, and rcu_irq_enter() should | ||
2582 | * not be called from NMI. | ||
2583 | */ | ||
2584 | if (unlikely(in_nmi())) | ||
2585 | return; | ||
2586 | |||
2587 | /* | ||
2588 | * It is possible that a function is being traced in a | ||
2589 | * location that RCU is not watching. A call to | ||
2590 | * rcu_irq_enter() will make sure that it is, but there's | ||
2591 | * a few internal rcu functions that could be traced | ||
2592 | * where that wont work either. In those cases, we just | ||
2593 | * do nothing. | ||
2594 | */ | ||
2595 | if (unlikely(rcu_irq_enter_disabled())) | ||
2596 | return; | ||
2597 | |||
2598 | rcu_irq_enter_irqson(); | ||
2599 | __ftrace_trace_stack(buffer, flags, skip, pc, NULL); | ||
2600 | rcu_irq_exit_irqson(); | ||
2572 | } | 2601 | } |
2573 | 2602 | ||
2574 | /** | 2603 | /** |
@@ -7550,6 +7579,7 @@ static int instance_rmdir(const char *name) | |||
7550 | } | 7579 | } |
7551 | 7580 | ||
7552 | tracing_set_nop(tr); | 7581 | tracing_set_nop(tr); |
7582 | clear_ftrace_function_probes(tr); | ||
7553 | event_trace_del_tracer(tr); | 7583 | event_trace_del_tracer(tr); |
7554 | ftrace_clear_pids(tr); | 7584 | ftrace_clear_pids(tr); |
7555 | ftrace_destroy_function_files(tr); | 7585 | ftrace_destroy_function_files(tr); |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 291a1bca5748..39fd77330aab 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -980,6 +980,7 @@ register_ftrace_function_probe(char *glob, struct trace_array *tr, | |||
980 | extern int | 980 | extern int |
981 | unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, | 981 | unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, |
982 | struct ftrace_probe_ops *ops); | 982 | struct ftrace_probe_ops *ops); |
983 | extern void clear_ftrace_function_probes(struct trace_array *tr); | ||
983 | 984 | ||
984 | int register_ftrace_command(struct ftrace_func_command *cmd); | 985 | int register_ftrace_command(struct ftrace_func_command *cmd); |
985 | int unregister_ftrace_command(struct ftrace_func_command *cmd); | 986 | int unregister_ftrace_command(struct ftrace_func_command *cmd); |
@@ -998,6 +999,10 @@ static inline __init int unregister_ftrace_command(char *cmd_name) | |||
998 | { | 999 | { |
999 | return -EINVAL; | 1000 | return -EINVAL; |
1000 | } | 1001 | } |
1002 | static inline void clear_ftrace_function_probes(struct trace_array *tr) | ||
1003 | { | ||
1004 | } | ||
1005 | |||
1001 | /* | 1006 | /* |
1002 | * The ops parameter passed in is usually undefined. | 1007 | * The ops parameter passed in is usually undefined. |
1003 | * This must be a macro. | 1008 | * This must be a macro. |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 8485f6738a87..c129fca6ec99 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -1535,6 +1535,11 @@ static __init int kprobe_trace_self_tests_init(void) | |||
1535 | 1535 | ||
1536 | end: | 1536 | end: |
1537 | release_all_trace_kprobes(); | 1537 | release_all_trace_kprobes(); |
1538 | /* | ||
1539 | * Wait for the optimizer work to finish. Otherwise it might fiddle | ||
1540 | * with probes in already freed __init text. | ||
1541 | */ | ||
1542 | wait_for_kprobe_optimizer(); | ||
1538 | if (warn) | 1543 | if (warn) |
1539 | pr_cont("NG: Some tests are failed. Please check them.\n"); | 1544 | pr_cont("NG: Some tests are failed. Please check them.\n"); |
1540 | else | 1545 | else |
diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest index 32e6211e1c6e..717581145cfc 100755 --- a/tools/testing/selftests/ftrace/ftracetest +++ b/tools/testing/selftests/ftrace/ftracetest | |||
@@ -58,7 +58,7 @@ parse_opts() { # opts | |||
58 | ;; | 58 | ;; |
59 | --verbose|-v|-vv) | 59 | --verbose|-v|-vv) |
60 | VERBOSE=$((VERBOSE + 1)) | 60 | VERBOSE=$((VERBOSE + 1)) |
61 | [ $1 == '-vv' ] && VERBOSE=$((VERBOSE + 1)) | 61 | [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1)) |
62 | shift 1 | 62 | shift 1 |
63 | ;; | 63 | ;; |
64 | --debug|-d) | 64 | --debug|-d) |
diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc index 07bb3e5930b4..aa31368851c9 100644 --- a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc | |||
@@ -48,7 +48,7 @@ test_event_enabled() { | |||
48 | e=`cat $EVENT_ENABLE` | 48 | e=`cat $EVENT_ENABLE` |
49 | if [ "$e" != $val ]; then | 49 | if [ "$e" != $val ]; then |
50 | echo "Expected $val but found $e" | 50 | echo "Expected $val but found $e" |
51 | exit -1 | 51 | exit 1 |
52 | fi | 52 | fi |
53 | } | 53 | } |
54 | 54 | ||
diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions index 9aec6fcb7729..f2019b37370d 100644 --- a/tools/testing/selftests/ftrace/test.d/functions +++ b/tools/testing/selftests/ftrace/test.d/functions | |||
@@ -34,10 +34,10 @@ reset_ftrace_filter() { # reset all triggers in set_ftrace_filter | |||
34 | echo > set_ftrace_filter | 34 | echo > set_ftrace_filter |
35 | grep -v '^#' set_ftrace_filter | while read t; do | 35 | grep -v '^#' set_ftrace_filter | while read t; do |
36 | tr=`echo $t | cut -d: -f2` | 36 | tr=`echo $t | cut -d: -f2` |
37 | if [ "$tr" == "" ]; then | 37 | if [ "$tr" = "" ]; then |
38 | continue | 38 | continue |
39 | fi | 39 | fi |
40 | if [ $tr == "enable_event" -o $tr == "disable_event" ]; then | 40 | if [ $tr = "enable_event" -o $tr = "disable_event" ]; then |
41 | tr=`echo $t | cut -d: -f1-4` | 41 | tr=`echo $t | cut -d: -f1-4` |
42 | limit=`echo $t | cut -d: -f5` | 42 | limit=`echo $t | cut -d: -f5` |
43 | else | 43 | else |
diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc index 4c5a061a5b4e..c73db7863adb 100644 --- a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc +++ b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc | |||
@@ -75,9 +75,13 @@ rmdir foo | |||
75 | if [ -d foo ]; then | 75 | if [ -d foo ]; then |
76 | fail "foo still exists" | 76 | fail "foo still exists" |
77 | fi | 77 | fi |
78 | exit 0 | ||
79 | |||
80 | 78 | ||
79 | mkdir foo | ||
80 | echo "schedule:enable_event:sched:sched_switch" > foo/set_ftrace_filter | ||
81 | rmdir foo | ||
82 | if [ -d foo ]; then | ||
83 | fail "foo still exists" | ||
84 | fi | ||
81 | 85 | ||
82 | 86 | ||
83 | instance_slam() { | 87 | instance_slam() { |