diff options
Diffstat (limited to 'kernel/trace/trace.c')
| -rw-r--r-- | kernel/trace/trace.c | 30 | 
1 files changed, 28 insertions, 2 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 82d9b8106cd..f8cf959bad4 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -17,7 +17,6 @@  #include <linux/writeback.h>  #include <linux/kallsyms.h>  #include <linux/seq_file.h> -#include <linux/smp_lock.h>  #include <linux/notifier.h>  #include <linux/irqflags.h>  #include <linux/debugfs.h> @@ -1284,6 +1283,8 @@ void trace_dump_stack(void)  	__ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count());  } +static DEFINE_PER_CPU(int, user_stack_count); +  void  ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)  { @@ -1302,6 +1303,18 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)  	if (unlikely(in_nmi()))  		return; +	/* +	 * prevent recursion, since the user stack tracing may +	 * trigger other kernel events. +	 */ +	preempt_disable(); +	if (__this_cpu_read(user_stack_count)) +		goto out; + +	__this_cpu_inc(user_stack_count); + + +  	event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK,  					  sizeof(*entry), flags, pc);  	if (!event) @@ -1319,6 +1332,11 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)  	save_stack_trace_user(&trace);  	if (!filter_check_discard(call, entry, buffer, event))  		ring_buffer_unlock_commit(buffer, event); + +	__this_cpu_dec(user_stack_count); + + out: +	preempt_enable();  }  #ifdef UNUSED @@ -2320,11 +2338,19 @@ tracing_write_stub(struct file *filp, const char __user *ubuf,  	return count;  } +static loff_t tracing_seek(struct file *file, loff_t offset, int origin) +{ +	if (file->f_mode & FMODE_READ) +		return seq_lseek(file, offset, origin); +	else +		return 0; +} +  static const struct file_operations tracing_fops = {  	.open		= tracing_open,  	.read		= seq_read,  	.write		= tracing_write_stub, -	.llseek		= seq_lseek, +	.llseek		= tracing_seek,  	.release	= tracing_release,  };  |