Commit f38f1d2aa5a3520cf05da7cd6bd12fe2b0c509b7

Authored by Steven Rostedt
Committed by Ingo Molnar
1 parent 40874491f9

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>
... ... @@ -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 }