]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/trace/trace_kdb.c
Merge tag 'powerpc-5.2-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
[linux.git] / kernel / trace / trace_kdb.c
index 810d78a8d14c76b02efa3dff91b63e52e4c66feb..6c1ae6b752d1997310dbc487808be4a01c749b40 100644 (file)
 #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,
@@ -70,11 +66,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))
@@ -89,10 +85,6 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
 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]);
@@ -106,17 +98,19 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
  */
 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 +123,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 +153,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;
 }