diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-22 22:40:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-22 22:40:39 -0400 |
commit | 7639dad93a5564579987abded4ec05e3db13659d (patch) | |
tree | d786a45e79672ee3ea04e93d60ec1da02cb17940 | |
parent | 77ed402b7f53cbe50ae8384a172a5b9713020400 (diff) | |
parent | 8329e818f14926a6040df86b2668568bde342ebf (diff) |
Merge tag 'trace-v4.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull motr tracing updates from Steven Rostedt:
"Three more changes.
- I forgot that I had another selftest to stress test the ftrace
instance creation. It was actually suppose to go into the 4.6
merge window, but I never committed it. I almost forgot about it
again, but noticed it was missing from your tree.
- Soumya PN sent me a clean up patch to not disable interrupts when
taking the tasklist_lock for read, as it's unnecessary because that
lock is never taken for write in irq context.
- Newer gcc's can cause the jump in the function_graph code to the
global ftrace_stub label to be a short jump instead of a long one.
As that jump is dynamically converted to jump to the trace code to
do function graph tracing, and that conversion expects a long jump
it can corrupt the ftrace_stub itself (it's directly after that
call). One way to prevent gcc from using a short jump is to
declare the ftrace_stub as a weak function, which we do here to
keep gcc from optimizing too much"
* tag 'trace-v4.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
ftrace/x86: Set ftrace_stub to weak to prevent gcc from using short jumps to it
ftrace: Don't disable irqs when taking the tasklist_lock read_lock
ftracetest: Add instance created, delete, read and enable event test
-rw-r--r-- | arch/x86/kernel/mcount_64.S | 3 | ||||
-rw-r--r-- | kernel/trace/ftrace.c | 5 | ||||
-rw-r--r-- | tools/testing/selftests/ftrace/test.d/instances/instance-event.tc | 143 |
3 files changed, 147 insertions, 4 deletions
diff --git a/arch/x86/kernel/mcount_64.S b/arch/x86/kernel/mcount_64.S index ed48a9f465f8..61924222a9e1 100644 --- a/arch/x86/kernel/mcount_64.S +++ b/arch/x86/kernel/mcount_64.S | |||
@@ -182,7 +182,8 @@ GLOBAL(ftrace_graph_call) | |||
182 | jmp ftrace_stub | 182 | jmp ftrace_stub |
183 | #endif | 183 | #endif |
184 | 184 | ||
185 | GLOBAL(ftrace_stub) | 185 | /* This is weak to keep gas from relaxing the jumps */ |
186 | WEAK(ftrace_stub) | ||
186 | retq | 187 | retq |
187 | END(ftrace_caller) | 188 | END(ftrace_caller) |
188 | 189 | ||
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index a6c8252d7776..900dbb1efff2 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -5737,7 +5737,6 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) | |||
5737 | { | 5737 | { |
5738 | int i; | 5738 | int i; |
5739 | int ret = 0; | 5739 | int ret = 0; |
5740 | unsigned long flags; | ||
5741 | int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE; | 5740 | int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE; |
5742 | struct task_struct *g, *t; | 5741 | struct task_struct *g, *t; |
5743 | 5742 | ||
@@ -5753,7 +5752,7 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) | |||
5753 | } | 5752 | } |
5754 | } | 5753 | } |
5755 | 5754 | ||
5756 | read_lock_irqsave(&tasklist_lock, flags); | 5755 | read_lock(&tasklist_lock); |
5757 | do_each_thread(g, t) { | 5756 | do_each_thread(g, t) { |
5758 | if (start == end) { | 5757 | if (start == end) { |
5759 | ret = -EAGAIN; | 5758 | ret = -EAGAIN; |
@@ -5771,7 +5770,7 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) | |||
5771 | } while_each_thread(g, t); | 5770 | } while_each_thread(g, t); |
5772 | 5771 | ||
5773 | unlock: | 5772 | unlock: |
5774 | read_unlock_irqrestore(&tasklist_lock, flags); | 5773 | read_unlock(&tasklist_lock); |
5775 | free: | 5774 | free: |
5776 | for (i = start; i < end; i++) | 5775 | for (i = start; i < end; i++) |
5777 | kfree(ret_stack_list[i]); | 5776 | kfree(ret_stack_list[i]); |
diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc new file mode 100644 index 000000000000..5f2abd03f16b --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc | |||
@@ -0,0 +1,143 @@ | |||
1 | #!/bin/sh | ||
2 | # description: Test creation and deletion of trace instances while setting an event | ||
3 | |||
4 | if [ ! -d instances ] ; then | ||
5 | echo "no instance directory with this kernel" | ||
6 | exit_unsupported; | ||
7 | fi | ||
8 | |||
9 | fail() { # mesg | ||
10 | rmdir foo 2>/dev/null | ||
11 | echo $1 | ||
12 | set -e | ||
13 | exit $FAIL | ||
14 | } | ||
15 | |||
16 | cd instances | ||
17 | |||
18 | # we don't want to fail on error | ||
19 | set +e | ||
20 | |||
21 | mkdir x | ||
22 | rmdir x | ||
23 | result=$? | ||
24 | |||
25 | if [ $result -ne 0 ]; then | ||
26 | echo "instance rmdir not supported" | ||
27 | exit_unsupported | ||
28 | fi | ||
29 | |||
30 | instance_slam() { | ||
31 | while :; do | ||
32 | mkdir foo 2> /dev/null | ||
33 | rmdir foo 2> /dev/null | ||
34 | done | ||
35 | } | ||
36 | |||
37 | instance_read() { | ||
38 | while :; do | ||
39 | cat foo/trace 1> /dev/null 2>&1 | ||
40 | done | ||
41 | } | ||
42 | |||
43 | instance_set() { | ||
44 | while :; do | ||
45 | echo 1 > foo/events/sched/sched_switch | ||
46 | done 2> /dev/null | ||
47 | } | ||
48 | |||
49 | instance_slam & | ||
50 | p1=$! | ||
51 | echo $p1 | ||
52 | |||
53 | instance_set & | ||
54 | p2=$! | ||
55 | echo $p2 | ||
56 | |||
57 | instance_read & | ||
58 | p3=$! | ||
59 | echo $p3 | ||
60 | |||
61 | sleep 1 | ||
62 | |||
63 | kill -1 $p3 | ||
64 | kill -1 $p2 | ||
65 | kill -1 $p1 | ||
66 | |||
67 | echo "Wait for processes to finish" | ||
68 | wait $p1 $p2 $p3 | ||
69 | echo "all processes finished, wait for cleanup" | ||
70 | sleep 1 | ||
71 | |||
72 | mkdir foo | ||
73 | ls foo > /dev/null | ||
74 | rmdir foo | ||
75 | if [ -d foo ]; then | ||
76 | fail "foo still exists" | ||
77 | fi | ||
78 | exit 0 | ||
79 | |||
80 | |||
81 | |||
82 | |||
83 | instance_slam() { | ||
84 | while :; do | ||
85 | mkdir x | ||
86 | mkdir y | ||
87 | mkdir z | ||
88 | rmdir x | ||
89 | rmdir y | ||
90 | rmdir z | ||
91 | done 2>/dev/null | ||
92 | } | ||
93 | |||
94 | instance_slam & | ||
95 | x=`jobs -l` | ||
96 | p1=`echo $x | cut -d' ' -f2` | ||
97 | echo $p1 | ||
98 | |||
99 | instance_slam & | ||
100 | x=`jobs -l | tail -1` | ||
101 | p2=`echo $x | cut -d' ' -f2` | ||
102 | echo $p2 | ||
103 | |||
104 | instance_slam & | ||
105 | x=`jobs -l | tail -1` | ||
106 | p3=`echo $x | cut -d' ' -f2` | ||
107 | echo $p3 | ||
108 | |||
109 | instance_slam & | ||
110 | x=`jobs -l | tail -1` | ||
111 | p4=`echo $x | cut -d' ' -f2` | ||
112 | echo $p4 | ||
113 | |||
114 | instance_slam & | ||
115 | x=`jobs -l | tail -1` | ||
116 | p5=`echo $x | cut -d' ' -f2` | ||
117 | echo $p5 | ||
118 | |||
119 | ls -lR >/dev/null | ||
120 | sleep 1 | ||
121 | |||
122 | kill -1 $p1 | ||
123 | kill -1 $p2 | ||
124 | kill -1 $p3 | ||
125 | kill -1 $p4 | ||
126 | kill -1 $p5 | ||
127 | |||
128 | echo "Wait for processes to finish" | ||
129 | wait $p1 $p2 $p3 $p4 $p5 | ||
130 | echo "all processes finished, wait for cleanup" | ||
131 | |||
132 | mkdir x y z | ||
133 | ls x y z | ||
134 | rmdir x y z | ||
135 | for d in x y z; do | ||
136 | if [ -d $d ]; then | ||
137 | fail "instance $d still exists" | ||
138 | fi | ||
139 | done | ||
140 | |||
141 | set -e | ||
142 | |||
143 | exit 0 | ||