diff options
Diffstat (limited to 'kernel/trace/trace_kdb.c')
| -rw-r--r-- | kernel/trace/trace_kdb.c | 67 | 
1 files changed, 40 insertions, 27 deletions
diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c index 810d78a8d14c..cca65044c14c 100644 --- a/kernel/trace/trace_kdb.c +++ b/kernel/trace/trace_kdb.c @@ -17,36 +17,28 @@  #include "trace.h"  #include "trace_output.h" -static void ftrace_dump_buf(int skip_lines, long cpu_file) +static struct trace_iterator iter; +static struct ring_buffer_iter *buffer_iter[CONFIG_NR_CPUS]; + +static void ftrace_dump_buf(int skip_entries, long cpu_file)  { -	/* use static because iter can be a bit big for the stack */ -	static struct trace_iterator iter; -	static struct ring_buffer_iter *buffer_iter[CONFIG_NR_CPUS];  	struct trace_array *tr;  	unsigned int old_userobj;  	int cnt = 0, cpu; -	trace_init_global_iter(&iter); -	iter.buffer_iter = buffer_iter;  	tr = iter.tr; -	for_each_tracing_cpu(cpu) { -		atomic_inc(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled); -	} -  	old_userobj = tr->trace_flags;  	/* don't look at user memory in panic mode */  	tr->trace_flags &= ~TRACE_ITER_SYM_USEROBJ;  	kdb_printf("Dumping ftrace buffer:\n"); +	if (skip_entries) +		kdb_printf("(skipping %d entries)\n", skip_entries); -	/* reset all but tr, trace, and overruns */ -	memset(&iter.seq, 0, -		   sizeof(struct trace_iterator) - -		   offsetof(struct trace_iterator, seq)); +	trace_iterator_reset(&iter);  	iter.iter_flags |= TRACE_FILE_LAT_FMT; -	iter.pos = -1;  	if (cpu_file == RING_BUFFER_ALL_CPUS) {  		for_each_tracing_cpu(cpu) { @@ -70,11 +62,11 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)  			kdb_printf("---------------------------------\n");  		cnt++; -		if (!skip_lines) { +		if (!skip_entries) {  			print_trace_line(&iter);  			trace_printk_seq(&iter.seq);  		} else { -			skip_lines--; +			skip_entries--;  		}  		if (KDB_FLAG(CMD_INTERRUPT)) @@ -90,10 +82,6 @@ out:  	tr->trace_flags = old_userobj;  	for_each_tracing_cpu(cpu) { -		atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled); -	} - -	for_each_tracing_cpu(cpu) {  		if (iter.buffer_iter[cpu]) {  			ring_buffer_read_finish(iter.buffer_iter[cpu]);  			iter.buffer_iter[cpu] = NULL; @@ -106,17 +94,19 @@ out:   */  static int kdb_ftdump(int argc, const char **argv)  { -	int skip_lines = 0; +	int skip_entries = 0;  	long cpu_file;  	char *cp; +	int cnt; +	int cpu;  	if (argc > 2)  		return KDB_ARGCOUNT;  	if (argc) { -		skip_lines = simple_strtol(argv[1], &cp, 0); +		skip_entries = simple_strtol(argv[1], &cp, 0);  		if (*cp) -			skip_lines = 0; +			skip_entries = 0;  	}  	if (argc == 2) { @@ -129,7 +119,29 @@ static int kdb_ftdump(int argc, const char **argv)  	}  	kdb_trap_printk++; -	ftrace_dump_buf(skip_lines, cpu_file); + +	trace_init_global_iter(&iter); +	iter.buffer_iter = buffer_iter; + +	for_each_tracing_cpu(cpu) { +		atomic_inc(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled); +	} + +	/* A negative skip_entries means skip all but the last entries */ +	if (skip_entries < 0) { +		if (cpu_file == RING_BUFFER_ALL_CPUS) +			cnt = trace_total_entries(NULL); +		else +			cnt = trace_total_entries_cpu(NULL, cpu_file); +		skip_entries = max(cnt + skip_entries, 0); +	} + +	ftrace_dump_buf(skip_entries, cpu_file); + +	for_each_tracing_cpu(cpu) { +		atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled); +	} +  	kdb_trap_printk--;  	return 0; @@ -137,8 +149,9 @@ static int kdb_ftdump(int argc, const char **argv)  static __init int kdb_ftrace_register(void)  { -	kdb_register_flags("ftdump", kdb_ftdump, "[skip_#lines] [cpu]", -			    "Dump ftrace log", 0, KDB_ENABLE_ALWAYS_SAFE); +	kdb_register_flags("ftdump", kdb_ftdump, "[skip_#entries] [cpu]", +			    "Dump ftrace log; -skip dumps last #entries", 0, +			    KDB_ENABLE_ALWAYS_SAFE);  	return 0;  }  |