diff options
Diffstat (limited to 'kernel/trace/trace_stack.c')
| -rw-r--r-- | kernel/trace/trace_stack.c | 52 | 
1 files changed, 48 insertions, 4 deletions
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index 0b863f2cbc8..4842c969c78 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c @@ -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;  }  |