| .. | .. | 
|---|
| 17 | 17 |  #include "trace.h" | 
|---|
| 18 | 18 |  #include "trace_output.h" | 
|---|
| 19 | 19 |   | 
|---|
| 20 |  | -static void ftrace_dump_buf(int skip_lines, long cpu_file)  | 
|---|
 | 20 | +static struct trace_iterator iter;  | 
|---|
 | 21 | +static struct ring_buffer_iter *buffer_iter[CONFIG_NR_CPUS];  | 
|---|
 | 22 | +  | 
|---|
 | 23 | +static void ftrace_dump_buf(int skip_entries, long cpu_file)  | 
|---|
| 21 | 24 |  { | 
|---|
| 22 |  | -	/* use static because iter can be a bit big for the stack */  | 
|---|
| 23 |  | -	static struct trace_iterator iter;  | 
|---|
| 24 |  | -	static struct ring_buffer_iter *buffer_iter[CONFIG_NR_CPUS];  | 
|---|
| 25 | 25 |  	struct trace_array *tr; | 
|---|
| 26 | 26 |  	unsigned int old_userobj; | 
|---|
| 27 | 27 |  	int cnt = 0, cpu; | 
|---|
| 28 | 28 |   | 
|---|
| 29 |  | -	trace_init_global_iter(&iter);  | 
|---|
| 30 |  | -	iter.buffer_iter = buffer_iter;  | 
|---|
| 31 | 29 |  	tr = iter.tr; | 
|---|
| 32 |  | -  | 
|---|
| 33 |  | -	for_each_tracing_cpu(cpu) {  | 
|---|
| 34 |  | -		atomic_inc(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);  | 
|---|
| 35 |  | -	}  | 
|---|
| 36 | 30 |   | 
|---|
| 37 | 31 |  	old_userobj = tr->trace_flags; | 
|---|
| 38 | 32 |   | 
|---|
| .. | .. | 
|---|
| 40 | 34 |  	tr->trace_flags &= ~TRACE_ITER_SYM_USEROBJ; | 
|---|
| 41 | 35 |   | 
|---|
| 42 | 36 |  	kdb_printf("Dumping ftrace buffer:\n"); | 
|---|
 | 37 | +	if (skip_entries)  | 
|---|
 | 38 | +		kdb_printf("(skipping %d entries)\n", skip_entries);  | 
|---|
| 43 | 39 |   | 
|---|
| 44 | 40 |  	trace_iterator_reset(&iter); | 
|---|
| 45 | 41 |  	iter.iter_flags |= TRACE_FILE_LAT_FMT; | 
|---|
| .. | .. | 
|---|
| 47 | 43 |  	if (cpu_file == RING_BUFFER_ALL_CPUS) { | 
|---|
| 48 | 44 |  		for_each_tracing_cpu(cpu) { | 
|---|
| 49 | 45 |  			iter.buffer_iter[cpu] = | 
|---|
| 50 |  | -			ring_buffer_read_prepare(iter.trace_buffer->buffer,  | 
|---|
 | 46 | +			ring_buffer_read_prepare(iter.array_buffer->buffer,  | 
|---|
| 51 | 47 |  						 cpu, GFP_ATOMIC); | 
|---|
| 52 | 48 |  			ring_buffer_read_start(iter.buffer_iter[cpu]); | 
|---|
| 53 | 49 |  			tracing_iter_reset(&iter, cpu); | 
|---|
| .. | .. | 
|---|
| 55 | 51 |  	} else { | 
|---|
| 56 | 52 |  		iter.cpu_file = cpu_file; | 
|---|
| 57 | 53 |  		iter.buffer_iter[cpu_file] = | 
|---|
| 58 |  | -			ring_buffer_read_prepare(iter.trace_buffer->buffer,  | 
|---|
 | 54 | +			ring_buffer_read_prepare(iter.array_buffer->buffer,  | 
|---|
| 59 | 55 |  						 cpu_file, GFP_ATOMIC); | 
|---|
| 60 | 56 |  		ring_buffer_read_start(iter.buffer_iter[cpu_file]); | 
|---|
| 61 | 57 |  		tracing_iter_reset(&iter, cpu_file); | 
|---|
| .. | .. | 
|---|
| 66 | 62 |  			kdb_printf("---------------------------------\n"); | 
|---|
| 67 | 63 |  		cnt++; | 
|---|
| 68 | 64 |   | 
|---|
| 69 |  | -		if (!skip_lines) {  | 
|---|
 | 65 | +		if (!skip_entries) {  | 
|---|
| 70 | 66 |  			print_trace_line(&iter); | 
|---|
| 71 | 67 |  			trace_printk_seq(&iter.seq); | 
|---|
| 72 | 68 |  		} else { | 
|---|
| 73 |  | -			skip_lines--;  | 
|---|
 | 69 | +			skip_entries--;  | 
|---|
| 74 | 70 |  		} | 
|---|
| 75 | 71 |   | 
|---|
| 76 | 72 |  		if (KDB_FLAG(CMD_INTERRUPT)) | 
|---|
| .. | .. | 
|---|
| 86 | 82 |  	tr->trace_flags = old_userobj; | 
|---|
| 87 | 83 |   | 
|---|
| 88 | 84 |  	for_each_tracing_cpu(cpu) { | 
|---|
| 89 |  | -		atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled);  | 
|---|
| 90 |  | -	}  | 
|---|
| 91 |  | -  | 
|---|
| 92 |  | -	for_each_tracing_cpu(cpu) {  | 
|---|
| 93 | 85 |  		if (iter.buffer_iter[cpu]) { | 
|---|
| 94 | 86 |  			ring_buffer_read_finish(iter.buffer_iter[cpu]); | 
|---|
| 95 | 87 |  			iter.buffer_iter[cpu] = NULL; | 
|---|
| .. | .. | 
|---|
| 102 | 94 |   */ | 
|---|
| 103 | 95 |  static int kdb_ftdump(int argc, const char **argv) | 
|---|
| 104 | 96 |  { | 
|---|
| 105 |  | -	int skip_lines = 0;  | 
|---|
 | 97 | +	int skip_entries = 0;  | 
|---|
| 106 | 98 |  	long cpu_file; | 
|---|
| 107 | 99 |  	char *cp; | 
|---|
 | 100 | +	int cnt;  | 
|---|
 | 101 | +	int cpu;  | 
|---|
| 108 | 102 |   | 
|---|
| 109 | 103 |  	if (argc > 2) | 
|---|
| 110 | 104 |  		return KDB_ARGCOUNT; | 
|---|
| 111 | 105 |   | 
|---|
| 112 | 106 |  	if (argc) { | 
|---|
| 113 |  | -		skip_lines = simple_strtol(argv[1], &cp, 0);  | 
|---|
 | 107 | +		skip_entries = simple_strtol(argv[1], &cp, 0);  | 
|---|
| 114 | 108 |  		if (*cp) | 
|---|
| 115 |  | -			skip_lines = 0;  | 
|---|
 | 109 | +			skip_entries = 0;  | 
|---|
| 116 | 110 |  	} | 
|---|
| 117 | 111 |   | 
|---|
| 118 | 112 |  	if (argc == 2) { | 
|---|
| .. | .. | 
|---|
| 125 | 119 |  	} | 
|---|
| 126 | 120 |   | 
|---|
| 127 | 121 |  	kdb_trap_printk++; | 
|---|
| 128 |  | -	ftrace_dump_buf(skip_lines, cpu_file);  | 
|---|
 | 122 | +  | 
|---|
 | 123 | +	trace_init_global_iter(&iter);  | 
|---|
 | 124 | +	iter.buffer_iter = buffer_iter;  | 
|---|
 | 125 | +  | 
|---|
 | 126 | +	for_each_tracing_cpu(cpu) {  | 
|---|
 | 127 | +		atomic_inc(&per_cpu_ptr(iter.array_buffer->data, cpu)->disabled);  | 
|---|
 | 128 | +	}  | 
|---|
 | 129 | +  | 
|---|
 | 130 | +	/* A negative skip_entries means skip all but the last entries */  | 
|---|
 | 131 | +	if (skip_entries < 0) {  | 
|---|
 | 132 | +		if (cpu_file == RING_BUFFER_ALL_CPUS)  | 
|---|
 | 133 | +			cnt = trace_total_entries(NULL);  | 
|---|
 | 134 | +		else  | 
|---|
 | 135 | +			cnt = trace_total_entries_cpu(NULL, cpu_file);  | 
|---|
 | 136 | +		skip_entries = max(cnt + skip_entries, 0);  | 
|---|
 | 137 | +	}  | 
|---|
 | 138 | +  | 
|---|
 | 139 | +	ftrace_dump_buf(skip_entries, cpu_file);  | 
|---|
 | 140 | +  | 
|---|
 | 141 | +	for_each_tracing_cpu(cpu) {  | 
|---|
 | 142 | +		atomic_dec(&per_cpu_ptr(iter.array_buffer->data, cpu)->disabled);  | 
|---|
 | 143 | +	}  | 
|---|
 | 144 | +  | 
|---|
| 129 | 145 |  	kdb_trap_printk--; | 
|---|
| 130 | 146 |   | 
|---|
| 131 | 147 |  	return 0; | 
|---|
| .. | .. | 
|---|
| 133 | 149 |   | 
|---|
| 134 | 150 |  static __init int kdb_ftrace_register(void) | 
|---|
| 135 | 151 |  { | 
|---|
| 136 |  | -	kdb_register_flags("ftdump", kdb_ftdump, "[skip_#lines] [cpu]",  | 
|---|
| 137 |  | -			    "Dump ftrace log", 0, KDB_ENABLE_ALWAYS_SAFE);  | 
|---|
 | 152 | +	kdb_register_flags("ftdump", kdb_ftdump, "[skip_#entries] [cpu]",  | 
|---|
 | 153 | +			    "Dump ftrace log; -skip dumps last #entries", 0,  | 
|---|
 | 154 | +			    KDB_ENABLE_ALWAYS_SAFE);  | 
|---|
| 138 | 155 |  	return 0; | 
|---|
| 139 | 156 |  } | 
|---|
| 140 | 157 |   | 
|---|