diff options
Diffstat (limited to 'kernel/trace/trace_stack.c')
| -rw-r--r-- | kernel/trace/trace_stack.c | 85 | 
1 files changed, 27 insertions, 58 deletions
| diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index eec648a0d673..5d16f73898db 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c @@ -18,44 +18,32 @@  #include "trace.h" -static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = -	 { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; -unsigned stack_trace_index[STACK_TRACE_ENTRIES]; +#define STACK_TRACE_ENTRIES 500 -/* - * Reserve one entry for the passed in ip. This will allow - * us to remove most or all of the stack size overhead - * added by the stack tracer itself. - */ -struct stack_trace stack_trace_max = { -	.max_entries		= STACK_TRACE_ENTRIES - 1, -	.entries		= &stack_dump_trace[0], -}; +static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES]; +static unsigned stack_trace_index[STACK_TRACE_ENTRIES]; -unsigned long stack_trace_max_size; -arch_spinlock_t stack_trace_max_lock = +static unsigned int stack_trace_nr_entries; +static unsigned long stack_trace_max_size; +static arch_spinlock_t stack_trace_max_lock =  	(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;  DEFINE_PER_CPU(int, disable_stack_tracer);  static DEFINE_MUTEX(stack_sysctl_mutex);  int stack_tracer_enabled; -static int last_stack_tracer_enabled; -void stack_trace_print(void) +static void print_max_stack(void)  {  	long i;  	int size;  	pr_emerg("        Depth    Size   Location    (%d entries)\n"  			   "        -----    ----   --------\n", -			   stack_trace_max.nr_entries); +			   stack_trace_nr_entries); -	for (i = 0; i < stack_trace_max.nr_entries; i++) { -		if (stack_dump_trace[i] == ULONG_MAX) -			break; -		if (i+1 == stack_trace_max.nr_entries || -				stack_dump_trace[i+1] == ULONG_MAX) +	for (i = 0; i < stack_trace_nr_entries; i++) { +		if (i + 1 == stack_trace_nr_entries)  			size = stack_trace_index[i];  		else  			size = stack_trace_index[i] - stack_trace_index[i+1]; @@ -65,16 +53,7 @@ void stack_trace_print(void)  	}  } -/* - * When arch-specific code overrides this function, the following - * data should be filled up, assuming stack_trace_max_lock is held to - * prevent concurrent updates. - *     stack_trace_index[] - *     stack_trace_max - *     stack_trace_max_size - */ -void __weak -check_stack(unsigned long ip, unsigned long *stack) +static void check_stack(unsigned long ip, unsigned long *stack)  {  	unsigned long this_size, flags; unsigned long *p, *top, *start;  	static int tracer_frame; @@ -110,13 +89,12 @@ check_stack(unsigned long ip, unsigned long *stack)  	stack_trace_max_size = this_size; -	stack_trace_max.nr_entries = 0; -	stack_trace_max.skip = 0; - -	save_stack_trace(&stack_trace_max); +	stack_trace_nr_entries = stack_trace_save(stack_dump_trace, +					       ARRAY_SIZE(stack_dump_trace) - 1, +					       0);  	/* Skip over the overhead of the stack tracer itself */ -	for (i = 0; i < stack_trace_max.nr_entries; i++) { +	for (i = 0; i < stack_trace_nr_entries; i++) {  		if (stack_dump_trace[i] == ip)  			break;  	} @@ -125,7 +103,7 @@ check_stack(unsigned long ip, unsigned long *stack)  	 * Some archs may not have the passed in ip in the dump.  	 * If that happens, we need to show everything.  	 */ -	if (i == stack_trace_max.nr_entries) +	if (i == stack_trace_nr_entries)  		i = 0;  	/* @@ -143,15 +121,13 @@ check_stack(unsigned long ip, unsigned long *stack)  	 * loop will only happen once. This code only takes place  	 * on a new max, so it is far from a fast path.  	 */ -	while (i < stack_trace_max.nr_entries) { +	while (i < stack_trace_nr_entries) {  		int found = 0;  		stack_trace_index[x] = this_size;  		p = start; -		for (; p < top && i < stack_trace_max.nr_entries; p++) { -			if (stack_dump_trace[i] == ULONG_MAX) -				break; +		for (; p < top && i < stack_trace_nr_entries; p++) {  			/*  			 * The READ_ONCE_NOCHECK is used to let KASAN know that  			 * this is not a stack-out-of-bounds error. @@ -182,12 +158,10 @@ check_stack(unsigned long ip, unsigned long *stack)  			i++;  	} -	stack_trace_max.nr_entries = x; -	for (; x < i; x++) -		stack_dump_trace[x] = ULONG_MAX; +	stack_trace_nr_entries = x;  	if (task_stack_end_corrupted(current)) { -		stack_trace_print(); +		print_max_stack();  		BUG();  	} @@ -286,7 +260,7 @@ __next(struct seq_file *m, loff_t *pos)  {  	long n = *pos - 1; -	if (n >= stack_trace_max.nr_entries || stack_dump_trace[n] == ULONG_MAX) +	if (n >= stack_trace_nr_entries)  		return NULL;  	m->private = (void *)n; @@ -350,7 +324,7 @@ static int t_show(struct seq_file *m, void *v)  		seq_printf(m, "        Depth    Size   Location"  			   "    (%d entries)\n"  			   "        -----    ----   --------\n", -			   stack_trace_max.nr_entries); +			   stack_trace_nr_entries);  		if (!stack_tracer_enabled && !stack_trace_max_size)  			print_disabled(m); @@ -360,12 +334,10 @@ static int t_show(struct seq_file *m, void *v)  	i = *(long *)v; -	if (i >= stack_trace_max.nr_entries || -	    stack_dump_trace[i] == ULONG_MAX) +	if (i >= stack_trace_nr_entries)  		return 0; -	if (i+1 == stack_trace_max.nr_entries || -	    stack_dump_trace[i+1] == ULONG_MAX) +	if (i + 1 == stack_trace_nr_entries)  		size = stack_trace_index[i];  	else  		size = stack_trace_index[i] - stack_trace_index[i+1]; @@ -422,23 +394,21 @@ stack_trace_sysctl(struct ctl_table *table, int write,  		   void __user *buffer, size_t *lenp,  		   loff_t *ppos)  { +	int was_enabled;  	int ret;  	mutex_lock(&stack_sysctl_mutex); +	was_enabled = !!stack_tracer_enabled;  	ret = proc_dointvec(table, write, buffer, lenp, ppos); -	if (ret || !write || -	    (last_stack_tracer_enabled == !!stack_tracer_enabled)) +	if (ret || !write || (was_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; @@ -454,7 +424,6 @@ static __init int enable_stacktrace(char *str)  		strncpy(stack_trace_filter_buf, str + len, COMMAND_LINE_SIZE);  	stack_tracer_enabled = 1; -	last_stack_tracer_enabled = 1;  	return 1;  }  __setup("stacktrace", enable_stacktrace); |