aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_stack.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-06 16:30:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-06 16:30:20 -0500
commit22402cd0af685c1a5d067c87db3051db7fff7709 (patch)
tree4f06ef31f643be28f3d4c92821df36b8ff321d9b /kernel/trace/trace_stack.c
parent7c623cac4939fb36916c029609dd22e3dec0a014 (diff)
parentd227c3ae4e94e5eb11dd780a811f59e1a7b74ccd (diff)
Merge tag 'trace-v4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracking updates from Steven Rostedt: "Most of the changes are clean ups and small fixes. Some of them have stable tags to them. I searched through my INBOX just as the merge window opened and found lots of patches to pull. I ran them through all my tests and they were in linux-next for a few days. Features added this release: ---------------------------- - Module globbing. You can now filter function tracing to several modules. # echo '*:mod:*snd*' > set_ftrace_filter (Dmitry Safonov) - Tracer specific options are now visible even when the tracer is not active. It was rather annoying that you can only see and modify tracer options after enabling the tracer. Now they are in the options/ directory even when the tracer is not active. Although they are still only visible when the tracer is active in the trace_options file. - Trace options are now per instance (although some of the tracer specific options are global) - New tracefs file: set_event_pid. If any pid is added to this file, then all events in the instance will filter out events that are not part of this pid. sched_switch and sched_wakeup events handle next and the wakee pids" * tag 'trace-v4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (68 commits) tracefs: Fix refcount imbalance in start_creating() tracing: Put back comma for empty fields in boot string parsing tracing: Apply tracer specific options from kernel command line. tracing: Add some documentation about set_event_pid ring_buffer: Remove unneeded smp_wmb() before wakeup of reader benchmark tracing: Allow dumping traces without tracking trace started cpus ring_buffer: Fix more races when terminating the producer in the benchmark ring_buffer: Do no not complete benchmark reader too early tracing: Remove redundant TP_ARGS redefining tracing: Rename max_stack_lock to stack_trace_max_lock tracing: Allow arch-specific stack tracer recordmcount: arm64: Replace the ignored mcount call into nop recordmcount: Fix endianness handling bug for nop_mcount tracepoints: Fix documentation of RCU lockdep checks tracing: ftrace_event_is_function() can return boolean tracing: is_legal_op() can return boolean ring-buffer: rb_event_is_commit() can return boolean ring-buffer: rb_per_cpu_empty() can return boolean ring_buffer: ring_buffer_empty{cpu}() can return boolean ring-buffer: rb_is_reader_page() can return boolean ...
Diffstat (limited to 'kernel/trace/trace_stack.c')
-rw-r--r--kernel/trace/trace_stack.c92
1 files changed, 49 insertions, 43 deletions
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 8abf1ba18085..dda9e6742950 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -16,24 +16,22 @@
16 16
17#include "trace.h" 17#include "trace.h"
18 18
19#define STACK_TRACE_ENTRIES 500
20
21static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = 19static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] =
22 { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; 20 { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX };
23static unsigned stack_dump_index[STACK_TRACE_ENTRIES]; 21unsigned stack_trace_index[STACK_TRACE_ENTRIES];
24 22
25/* 23/*
26 * Reserve one entry for the passed in ip. This will allow 24 * Reserve one entry for the passed in ip. This will allow
27 * us to remove most or all of the stack size overhead 25 * us to remove most or all of the stack size overhead
28 * added by the stack tracer itself. 26 * added by the stack tracer itself.
29 */ 27 */
30static struct stack_trace max_stack_trace = { 28struct stack_trace stack_trace_max = {
31 .max_entries = STACK_TRACE_ENTRIES - 1, 29 .max_entries = STACK_TRACE_ENTRIES - 1,
32 .entries = &stack_dump_trace[0], 30 .entries = &stack_dump_trace[0],
33}; 31};
34 32
35static unsigned long max_stack_size; 33unsigned long stack_trace_max_size;
36static arch_spinlock_t max_stack_lock = 34arch_spinlock_t stack_trace_max_lock =
37 (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; 35 (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
38 36
39static DEFINE_PER_CPU(int, trace_active); 37static DEFINE_PER_CPU(int, trace_active);
@@ -42,30 +40,38 @@ static DEFINE_MUTEX(stack_sysctl_mutex);
42int stack_tracer_enabled; 40int stack_tracer_enabled;
43static int last_stack_tracer_enabled; 41static int last_stack_tracer_enabled;
44 42
45static inline void print_max_stack(void) 43void stack_trace_print(void)
46{ 44{
47 long i; 45 long i;
48 int size; 46 int size;
49 47
50 pr_emerg(" Depth Size Location (%d entries)\n" 48 pr_emerg(" Depth Size Location (%d entries)\n"
51 " ----- ---- --------\n", 49 " ----- ---- --------\n",
52 max_stack_trace.nr_entries); 50 stack_trace_max.nr_entries);
53 51
54 for (i = 0; i < max_stack_trace.nr_entries; i++) { 52 for (i = 0; i < stack_trace_max.nr_entries; i++) {
55 if (stack_dump_trace[i] == ULONG_MAX) 53 if (stack_dump_trace[i] == ULONG_MAX)
56 break; 54 break;
57 if (i+1 == max_stack_trace.nr_entries || 55 if (i+1 == stack_trace_max.nr_entries ||
58 stack_dump_trace[i+1] == ULONG_MAX) 56 stack_dump_trace[i+1] == ULONG_MAX)
59 size = stack_dump_index[i]; 57 size = stack_trace_index[i];
60 else 58 else
61 size = stack_dump_index[i] - stack_dump_index[i+1]; 59 size = stack_trace_index[i] - stack_trace_index[i+1];
62 60
63 pr_emerg("%3ld) %8d %5d %pS\n", i, stack_dump_index[i], 61 pr_emerg("%3ld) %8d %5d %pS\n", i, stack_trace_index[i],
64 size, (void *)stack_dump_trace[i]); 62 size, (void *)stack_dump_trace[i]);
65 } 63 }
66} 64}
67 65
68static inline void 66/*
67 * When arch-specific code overides this function, the following
68 * data should be filled up, assuming stack_trace_max_lock is held to
69 * prevent concurrent updates.
70 * stack_trace_index[]
71 * stack_trace_max
72 * stack_trace_max_size
73 */
74void __weak
69check_stack(unsigned long ip, unsigned long *stack) 75check_stack(unsigned long ip, unsigned long *stack)
70{ 76{
71 unsigned long this_size, flags; unsigned long *p, *top, *start; 77 unsigned long this_size, flags; unsigned long *p, *top, *start;
@@ -78,7 +84,7 @@ check_stack(unsigned long ip, unsigned long *stack)
78 /* Remove the frame of the tracer */ 84 /* Remove the frame of the tracer */
79 this_size -= frame_size; 85 this_size -= frame_size;
80 86
81 if (this_size <= max_stack_size) 87 if (this_size <= stack_trace_max_size)
82 return; 88 return;
83 89
84 /* we do not handle interrupt stacks yet */ 90 /* we do not handle interrupt stacks yet */
@@ -90,7 +96,7 @@ check_stack(unsigned long ip, unsigned long *stack)
90 return; 96 return;
91 97
92 local_irq_save(flags); 98 local_irq_save(flags);
93 arch_spin_lock(&max_stack_lock); 99 arch_spin_lock(&stack_trace_max_lock);
94 100
95 /* 101 /*
96 * RCU may not be watching, make it see us. 102 * RCU may not be watching, make it see us.
@@ -103,18 +109,18 @@ check_stack(unsigned long ip, unsigned long *stack)
103 this_size -= tracer_frame; 109 this_size -= tracer_frame;
104 110
105 /* a race could have already updated it */ 111 /* a race could have already updated it */
106 if (this_size <= max_stack_size) 112 if (this_size <= stack_trace_max_size)
107 goto out; 113 goto out;
108 114
109 max_stack_size = this_size; 115 stack_trace_max_size = this_size;
110 116
111 max_stack_trace.nr_entries = 0; 117 stack_trace_max.nr_entries = 0;
112 max_stack_trace.skip = 3; 118 stack_trace_max.skip = 3;
113 119
114 save_stack_trace(&max_stack_trace); 120 save_stack_trace(&stack_trace_max);
115 121
116 /* Skip over the overhead of the stack tracer itself */ 122 /* Skip over the overhead of the stack tracer itself */
117 for (i = 0; i < max_stack_trace.nr_entries; i++) { 123 for (i = 0; i < stack_trace_max.nr_entries; i++) {
118 if (stack_dump_trace[i] == ip) 124 if (stack_dump_trace[i] == ip)
119 break; 125 break;
120 } 126 }
@@ -134,18 +140,18 @@ check_stack(unsigned long ip, unsigned long *stack)
134 * loop will only happen once. This code only takes place 140 * loop will only happen once. This code only takes place
135 * on a new max, so it is far from a fast path. 141 * on a new max, so it is far from a fast path.
136 */ 142 */
137 while (i < max_stack_trace.nr_entries) { 143 while (i < stack_trace_max.nr_entries) {
138 int found = 0; 144 int found = 0;
139 145
140 stack_dump_index[x] = this_size; 146 stack_trace_index[x] = this_size;
141 p = start; 147 p = start;
142 148
143 for (; p < top && i < max_stack_trace.nr_entries; p++) { 149 for (; p < top && i < stack_trace_max.nr_entries; p++) {
144 if (stack_dump_trace[i] == ULONG_MAX) 150 if (stack_dump_trace[i] == ULONG_MAX)
145 break; 151 break;
146 if (*p == stack_dump_trace[i]) { 152 if (*p == stack_dump_trace[i]) {
147 stack_dump_trace[x] = stack_dump_trace[i++]; 153 stack_dump_trace[x] = stack_dump_trace[i++];
148 this_size = stack_dump_index[x++] = 154 this_size = stack_trace_index[x++] =
149 (top - p) * sizeof(unsigned long); 155 (top - p) * sizeof(unsigned long);
150 found = 1; 156 found = 1;
151 /* Start the search from here */ 157 /* Start the search from here */
@@ -160,7 +166,7 @@ check_stack(unsigned long ip, unsigned long *stack)
160 if (unlikely(!tracer_frame)) { 166 if (unlikely(!tracer_frame)) {
161 tracer_frame = (p - stack) * 167 tracer_frame = (p - stack) *
162 sizeof(unsigned long); 168 sizeof(unsigned long);
163 max_stack_size -= tracer_frame; 169 stack_trace_max_size -= tracer_frame;
164 } 170 }
165 } 171 }
166 } 172 }
@@ -169,18 +175,18 @@ check_stack(unsigned long ip, unsigned long *stack)
169 i++; 175 i++;
170 } 176 }
171 177
172 max_stack_trace.nr_entries = x; 178 stack_trace_max.nr_entries = x;
173 for (; x < i; x++) 179 for (; x < i; x++)
174 stack_dump_trace[x] = ULONG_MAX; 180 stack_dump_trace[x] = ULONG_MAX;
175 181
176 if (task_stack_end_corrupted(current)) { 182 if (task_stack_end_corrupted(current)) {
177 print_max_stack(); 183 stack_trace_print();
178 BUG(); 184 BUG();
179 } 185 }
180 186
181 out: 187 out:
182 rcu_irq_exit(); 188 rcu_irq_exit();
183 arch_spin_unlock(&max_stack_lock); 189 arch_spin_unlock(&stack_trace_max_lock);
184 local_irq_restore(flags); 190 local_irq_restore(flags);
185} 191}
186 192
@@ -251,9 +257,9 @@ stack_max_size_write(struct file *filp, const char __user *ubuf,
251 cpu = smp_processor_id(); 257 cpu = smp_processor_id();
252 per_cpu(trace_active, cpu)++; 258 per_cpu(trace_active, cpu)++;
253 259
254 arch_spin_lock(&max_stack_lock); 260 arch_spin_lock(&stack_trace_max_lock);
255 *ptr = val; 261 *ptr = val;
256 arch_spin_unlock(&max_stack_lock); 262 arch_spin_unlock(&stack_trace_max_lock);
257 263
258 per_cpu(trace_active, cpu)--; 264 per_cpu(trace_active, cpu)--;
259 local_irq_restore(flags); 265 local_irq_restore(flags);
@@ -273,7 +279,7 @@ __next(struct seq_file *m, loff_t *pos)
273{ 279{
274 long n = *pos - 1; 280 long n = *pos - 1;
275 281
276 if (n > max_stack_trace.nr_entries || stack_dump_trace[n] == ULONG_MAX) 282 if (n > stack_trace_max.nr_entries || stack_dump_trace[n] == ULONG_MAX)
277 return NULL; 283 return NULL;
278 284
279 m->private = (void *)n; 285 m->private = (void *)n;
@@ -296,7 +302,7 @@ static void *t_start(struct seq_file *m, loff_t *pos)
296 cpu = smp_processor_id(); 302 cpu = smp_processor_id();
297 per_cpu(trace_active, cpu)++; 303 per_cpu(trace_active, cpu)++;
298 304
299 arch_spin_lock(&max_stack_lock); 305 arch_spin_lock(&stack_trace_max_lock);
300 306
301 if (*pos == 0) 307 if (*pos == 0)
302 return SEQ_START_TOKEN; 308 return SEQ_START_TOKEN;
@@ -308,7 +314,7 @@ static void t_stop(struct seq_file *m, void *p)
308{ 314{
309 int cpu; 315 int cpu;
310 316
311 arch_spin_unlock(&max_stack_lock); 317 arch_spin_unlock(&stack_trace_max_lock);
312 318
313 cpu = smp_processor_id(); 319 cpu = smp_processor_id();
314 per_cpu(trace_active, cpu)--; 320 per_cpu(trace_active, cpu)--;
@@ -343,9 +349,9 @@ static int t_show(struct seq_file *m, void *v)
343 seq_printf(m, " Depth Size Location" 349 seq_printf(m, " Depth Size Location"
344 " (%d entries)\n" 350 " (%d entries)\n"
345 " ----- ---- --------\n", 351 " ----- ---- --------\n",
346 max_stack_trace.nr_entries); 352 stack_trace_max.nr_entries);
347 353
348 if (!stack_tracer_enabled && !max_stack_size) 354 if (!stack_tracer_enabled && !stack_trace_max_size)
349 print_disabled(m); 355 print_disabled(m);
350 356
351 return 0; 357 return 0;
@@ -353,17 +359,17 @@ static int t_show(struct seq_file *m, void *v)
353 359
354 i = *(long *)v; 360 i = *(long *)v;
355 361
356 if (i >= max_stack_trace.nr_entries || 362 if (i >= stack_trace_max.nr_entries ||
357 stack_dump_trace[i] == ULONG_MAX) 363 stack_dump_trace[i] == ULONG_MAX)
358 return 0; 364 return 0;
359 365
360 if (i+1 == max_stack_trace.nr_entries || 366 if (i+1 == stack_trace_max.nr_entries ||
361 stack_dump_trace[i+1] == ULONG_MAX) 367 stack_dump_trace[i+1] == ULONG_MAX)
362 size = stack_dump_index[i]; 368 size = stack_trace_index[i];
363 else 369 else
364 size = stack_dump_index[i] - stack_dump_index[i+1]; 370 size = stack_trace_index[i] - stack_trace_index[i+1];
365 371
366 seq_printf(m, "%3ld) %8d %5d ", i, stack_dump_index[i], size); 372 seq_printf(m, "%3ld) %8d %5d ", i, stack_trace_index[i], size);
367 373
368 trace_lookup_stack(m, i); 374 trace_lookup_stack(m, i);
369 375
@@ -453,7 +459,7 @@ static __init int stack_trace_init(void)
453 return 0; 459 return 0;
454 460
455 trace_create_file("stack_max_size", 0644, d_tracer, 461 trace_create_file("stack_max_size", 0644, d_tracer,
456 &max_stack_size, &stack_max_size_fops); 462 &stack_trace_max_size, &stack_max_size_fops);
457 463
458 trace_create_file("stack_trace", 0444, d_tracer, 464 trace_create_file("stack_trace", 0444, d_tracer,
459 NULL, &stack_trace_fops); 465 NULL, &stack_trace_fops);