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