trace: add a way to enable or disable the stack tracer
authorSteven Rostedt <srostedt@redhat.com>
Wed, 17 Dec 2008 04:06:40 +0000 (23:06 -0500)
committerIngo Molnar <mingo@elte.hu>
Thu, 18 Dec 2008 11:56:24 +0000 (12:56 +0100)
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>
Documentation/kernel-parameters.txt
include/linux/ftrace.h
kernel/sysctl.c
kernel/trace/Kconfig
kernel/trace/trace_stack.c

index 2919a2e919388cd572a7e99559c90e92dc544a28..edab81c131823ea6b863ea9373575c42df56b2b7 100644 (file)
@@ -89,6 +89,7 @@ parameter is applicable:
        SPARC   Sparc architecture is enabled.
        SWSUSP  Software suspend (hibernation) is enabled.
        SUSPEND System suspend states are enabled.
+       FTRACE  Function tracing enabled.
        TS      Appropriate touchscreen support is enabled.
        USB     USB support is enabled.
        USBHID  USB Human Interface Device support is enabled.
@@ -2173,6 +2174,9 @@ and is between 256 and 4096 characters. It is defined in the file
        st=             [HW,SCSI] SCSI tape parameters (buffers, etc.)
                        See Documentation/scsi/st.txt.
 
+       stacktrace      [FTRACE]
+                       Enabled the stack tracer on boot up.
+
        sti=            [PARISC,HW]
                        Format: <num>
                        Set the STI (builtin display/keyboard on the HP-PARISC
index 44020f31bd817a6dbf1f038f2d9b6500db942281..6b0db53caa7d464b539579937d9dc1e17b000a63 100644 (file)
@@ -86,6 +86,14 @@ static inline void ftrace_stop(void) { }
 static inline void ftrace_start(void) { }
 #endif /* CONFIG_FUNCTION_TRACER */
 
+#ifdef CONFIG_STACK_TRACER
+extern int stack_tracer_enabled;
+int
+stack_trace_sysctl(struct ctl_table *table, int write,
+                  struct file *file, void __user *buffer, size_t *lenp,
+                  loff_t *ppos);
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 /* asm/ftrace.h must be defined for archs supporting dynamic ftrace */
 #include <asm/ftrace.h>
index c83f566e940abaac4cdef8b7744746104aaabd38..6ac501a2dcc6aaf74d59b258f3f26a0b52f23b59 100644 (file)
@@ -487,6 +487,16 @@ static struct ctl_table kern_table[] = {
                .proc_handler   = &ftrace_enable_sysctl,
        },
 #endif
+#ifdef CONFIG_STACK_TRACER
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "stack_tracer_enabled",
+               .data           = &stack_tracer_enabled,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &stack_trace_sysctl,
+       },
+#endif
 #ifdef CONFIG_TRACING
        {
                .ctl_name       = CTL_UNNUMBERED,
index d8bae6f4219ee32cc869fbaaee22a488553289e1..e2a4ff6fc3a6bb1509472dad03d0ad41df855748 100644 (file)
@@ -244,10 +244,15 @@ config STACK_TRACER
 
          This tracer works by hooking into every function call that the
          kernel executes, and keeping a maximum stack depth value and
-         stack-trace saved. Because this logic has to execute in every
-         kernel function, all the time, this option can slow down the
-         kernel measurably and is generally intended for kernel
-         developers only.
+         stack-trace saved.  If this is configured with DYNAMIC_FTRACE
+         then it will not have any overhead while the stack tracer
+         is disabled.
+
+         To enable the stack tracer on bootup, pass in 'stacktrace'
+         on the kernel command line.
+
+         The stack tracer can also be enabled or disabled via the
+         sysctl kernel.stack_tracer_enabled
 
          Say N if unsure.
 
index 0b863f2cbc8e3ff04c9ea8347f4ffb6795dab446..4842c969c7855ea749836b18f862cce95343f578 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/debugfs.h>
 #include <linux/ftrace.h>
 #include <linux/module.h>
+#include <linux/sysctl.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include "trace.h"
@@ -31,6 +32,10 @@ static raw_spinlock_t max_stack_lock =
 
 static int stack_trace_disabled __read_mostly;
 static DEFINE_PER_CPU(int, trace_active);
+static DEFINE_MUTEX(stack_sysctl_mutex);
+
+int stack_tracer_enabled;
+static int last_stack_tracer_enabled;
 
 static inline void check_stack(void)
 {
@@ -174,7 +179,7 @@ stack_max_size_write(struct file *filp, const char __user *ubuf,
        return count;
 }
 
-static struct file_operations stack_max_size_fops = {
+static const struct file_operations stack_max_size_fops = {
        .open           = tracing_open_generic,
        .read           = stack_max_size_read,
        .write          = stack_max_size_write,
@@ -272,7 +277,7 @@ static int t_show(struct seq_file *m, void *v)
        return 0;
 }
 
-static struct seq_operations stack_trace_seq_ops = {
+static const struct seq_operations stack_trace_seq_ops = {
        .start          = t_start,
        .next           = t_next,
        .stop           = t_stop,
@@ -288,12 +293,48 @@ static int stack_trace_open(struct inode *inode, struct file *file)
        return ret;
 }
 
-static struct file_operations stack_trace_fops = {
+static const struct file_operations stack_trace_fops = {
        .open           = stack_trace_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
 };
 
+int
+stack_trace_sysctl(struct ctl_table *table, int write,
+                  struct file *file, void __user *buffer, size_t *lenp,
+                  loff_t *ppos)
+{
+       int ret;
+
+       mutex_lock(&stack_sysctl_mutex);
+
+       ret  = proc_dointvec(table, write, file, buffer, lenp, ppos);
+
+       if (ret || !write ||
+           (last_stack_tracer_enabled == stack_tracer_enabled))
+               goto out;
+
+       last_stack_tracer_enabled = stack_tracer_enabled;
+
+       if (stack_tracer_enabled)
+               register_ftrace_function(&trace_ops);
+       else
+               unregister_ftrace_function(&trace_ops);
+
+ out:
+       mutex_unlock(&stack_sysctl_mutex);
+       return ret;
+}
+
+static int start_stack_trace __initdata;
+
+static __init int enable_stacktrace(char *str)
+{
+       start_stack_trace = 1;
+       return 1;
+}
+__setup("stacktrace", enable_stacktrace);
+
 static __init int stack_trace_init(void)
 {
        struct dentry *d_tracer;
@@ -311,7 +352,10 @@ static __init int stack_trace_init(void)
        if (!entry)
                pr_warning("Could not create debugfs 'stack_trace' entry\n");
 
-       register_ftrace_function(&trace_ops);
+       if (start_stack_trace) {
+               register_ftrace_function(&trace_ops);
+               stack_tracer_enabled = 1;
+       }
 
        return 0;
 }