Commit f38f1d2aa5a3520cf05da7cd6bd12fe2b0c509b7
Committed by
Ingo Molnar
1 parent
40874491f9
Exists in
master
and in
4 other branches
trace: add a way to enable or disable the stack tracer
Impact: enhancement to stack tracer The stack tracer currently is either on when configured in or off when it is not. It can not be disabled when it is configured on. (besides disabling the function tracer that it uses) This patch adds a way to enable or disable the stack tracer at run time. It defaults off on bootup, but a kernel parameter 'stacktrace' has been added to enable it on bootup. A new sysctl has been added "kernel.stack_tracer_enabled" to let the user enable or disable the stack tracer at run time. Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 5 changed files with 79 additions and 8 deletions Side-by-side Diff
Documentation/kernel-parameters.txt
... | ... | @@ -89,6 +89,7 @@ |
89 | 89 | SPARC Sparc architecture is enabled. |
90 | 90 | SWSUSP Software suspend (hibernation) is enabled. |
91 | 91 | SUSPEND System suspend states are enabled. |
92 | + FTRACE Function tracing enabled. | |
92 | 93 | TS Appropriate touchscreen support is enabled. |
93 | 94 | USB USB support is enabled. |
94 | 95 | USBHID USB Human Interface Device support is enabled. |
... | ... | @@ -2172,6 +2173,9 @@ |
2172 | 2173 | |
2173 | 2174 | st= [HW,SCSI] SCSI tape parameters (buffers, etc.) |
2174 | 2175 | See Documentation/scsi/st.txt. |
2176 | + | |
2177 | + stacktrace [FTRACE] | |
2178 | + Enabled the stack tracer on boot up. | |
2175 | 2179 | |
2176 | 2180 | sti= [PARISC,HW] |
2177 | 2181 | Format: <num> |
include/linux/ftrace.h
... | ... | @@ -86,6 +86,14 @@ |
86 | 86 | static inline void ftrace_start(void) { } |
87 | 87 | #endif /* CONFIG_FUNCTION_TRACER */ |
88 | 88 | |
89 | +#ifdef CONFIG_STACK_TRACER | |
90 | +extern int stack_tracer_enabled; | |
91 | +int | |
92 | +stack_trace_sysctl(struct ctl_table *table, int write, | |
93 | + struct file *file, void __user *buffer, size_t *lenp, | |
94 | + loff_t *ppos); | |
95 | +#endif | |
96 | + | |
89 | 97 | #ifdef CONFIG_DYNAMIC_FTRACE |
90 | 98 | /* asm/ftrace.h must be defined for archs supporting dynamic ftrace */ |
91 | 99 | #include <asm/ftrace.h> |
kernel/sysctl.c
... | ... | @@ -487,6 +487,16 @@ |
487 | 487 | .proc_handler = &ftrace_enable_sysctl, |
488 | 488 | }, |
489 | 489 | #endif |
490 | +#ifdef CONFIG_STACK_TRACER | |
491 | + { | |
492 | + .ctl_name = CTL_UNNUMBERED, | |
493 | + .procname = "stack_tracer_enabled", | |
494 | + .data = &stack_tracer_enabled, | |
495 | + .maxlen = sizeof(int), | |
496 | + .mode = 0644, | |
497 | + .proc_handler = &stack_trace_sysctl, | |
498 | + }, | |
499 | +#endif | |
490 | 500 | #ifdef CONFIG_TRACING |
491 | 501 | { |
492 | 502 | .ctl_name = CTL_UNNUMBERED, |
kernel/trace/Kconfig
... | ... | @@ -244,10 +244,15 @@ |
244 | 244 | |
245 | 245 | This tracer works by hooking into every function call that the |
246 | 246 | kernel executes, and keeping a maximum stack depth value and |
247 | - stack-trace saved. Because this logic has to execute in every | |
248 | - kernel function, all the time, this option can slow down the | |
249 | - kernel measurably and is generally intended for kernel | |
250 | - developers only. | |
247 | + stack-trace saved. If this is configured with DYNAMIC_FTRACE | |
248 | + then it will not have any overhead while the stack tracer | |
249 | + is disabled. | |
250 | + | |
251 | + To enable the stack tracer on bootup, pass in 'stacktrace' | |
252 | + on the kernel command line. | |
253 | + | |
254 | + The stack tracer can also be enabled or disabled via the | |
255 | + sysctl kernel.stack_tracer_enabled | |
251 | 256 | |
252 | 257 | Say N if unsure. |
253 | 258 |
kernel/trace/trace_stack.c
... | ... | @@ -10,6 +10,7 @@ |
10 | 10 | #include <linux/debugfs.h> |
11 | 11 | #include <linux/ftrace.h> |
12 | 12 | #include <linux/module.h> |
13 | +#include <linux/sysctl.h> | |
13 | 14 | #include <linux/init.h> |
14 | 15 | #include <linux/fs.h> |
15 | 16 | #include "trace.h" |
16 | 17 | |
... | ... | @@ -31,7 +32,11 @@ |
31 | 32 | |
32 | 33 | static int stack_trace_disabled __read_mostly; |
33 | 34 | static DEFINE_PER_CPU(int, trace_active); |
35 | +static DEFINE_MUTEX(stack_sysctl_mutex); | |
34 | 36 | |
37 | +int stack_tracer_enabled; | |
38 | +static int last_stack_tracer_enabled; | |
39 | + | |
35 | 40 | static inline void check_stack(void) |
36 | 41 | { |
37 | 42 | unsigned long this_size, flags; |
... | ... | @@ -174,7 +179,7 @@ |
174 | 179 | return count; |
175 | 180 | } |
176 | 181 | |
177 | -static struct file_operations stack_max_size_fops = { | |
182 | +static const struct file_operations stack_max_size_fops = { | |
178 | 183 | .open = tracing_open_generic, |
179 | 184 | .read = stack_max_size_read, |
180 | 185 | .write = stack_max_size_write, |
... | ... | @@ -272,7 +277,7 @@ |
272 | 277 | return 0; |
273 | 278 | } |
274 | 279 | |
275 | -static struct seq_operations stack_trace_seq_ops = { | |
280 | +static const struct seq_operations stack_trace_seq_ops = { | |
276 | 281 | .start = t_start, |
277 | 282 | .next = t_next, |
278 | 283 | .stop = t_stop, |
279 | 284 | |
... | ... | @@ -288,12 +293,48 @@ |
288 | 293 | return ret; |
289 | 294 | } |
290 | 295 | |
291 | -static struct file_operations stack_trace_fops = { | |
296 | +static const struct file_operations stack_trace_fops = { | |
292 | 297 | .open = stack_trace_open, |
293 | 298 | .read = seq_read, |
294 | 299 | .llseek = seq_lseek, |
295 | 300 | }; |
296 | 301 | |
302 | +int | |
303 | +stack_trace_sysctl(struct ctl_table *table, int write, | |
304 | + struct file *file, void __user *buffer, size_t *lenp, | |
305 | + loff_t *ppos) | |
306 | +{ | |
307 | + int ret; | |
308 | + | |
309 | + mutex_lock(&stack_sysctl_mutex); | |
310 | + | |
311 | + ret = proc_dointvec(table, write, file, buffer, lenp, ppos); | |
312 | + | |
313 | + if (ret || !write || | |
314 | + (last_stack_tracer_enabled == stack_tracer_enabled)) | |
315 | + goto out; | |
316 | + | |
317 | + last_stack_tracer_enabled = stack_tracer_enabled; | |
318 | + | |
319 | + if (stack_tracer_enabled) | |
320 | + register_ftrace_function(&trace_ops); | |
321 | + else | |
322 | + unregister_ftrace_function(&trace_ops); | |
323 | + | |
324 | + out: | |
325 | + mutex_unlock(&stack_sysctl_mutex); | |
326 | + return ret; | |
327 | +} | |
328 | + | |
329 | +static int start_stack_trace __initdata; | |
330 | + | |
331 | +static __init int enable_stacktrace(char *str) | |
332 | +{ | |
333 | + start_stack_trace = 1; | |
334 | + return 1; | |
335 | +} | |
336 | +__setup("stacktrace", enable_stacktrace); | |
337 | + | |
297 | 338 | static __init int stack_trace_init(void) |
298 | 339 | { |
299 | 340 | struct dentry *d_tracer; |
... | ... | @@ -311,7 +352,10 @@ |
311 | 352 | if (!entry) |
312 | 353 | pr_warning("Could not create debugfs 'stack_trace' entry\n"); |
313 | 354 | |
314 | - register_ftrace_function(&trace_ops); | |
355 | + if (start_stack_trace) { | |
356 | + register_ftrace_function(&trace_ops); | |
357 | + stack_tracer_enabled = 1; | |
358 | + } | |
315 | 359 | |
316 | 360 | return 0; |
317 | 361 | } |