Merge tag 'ktest-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[linux-2.6-microblaze.git] / kernel / trace / trace_kdb.c
index 810d78a..9da7610 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,
-                  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) {
                        iter.buffer_iter[cpu] =
-                       ring_buffer_read_prepare(iter.trace_buffer->buffer,
+                       ring_buffer_read_prepare(iter.array_buffer->buffer,
                                                 cpu, GFP_ATOMIC);
                        ring_buffer_read_start(iter.buffer_iter[cpu]);
                        tracing_iter_reset(&iter, cpu);
@@ -59,7 +51,7 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file)
        } else {
                iter.cpu_file = cpu_file;
                iter.buffer_iter[cpu_file] =
-                       ring_buffer_read_prepare(iter.trace_buffer->buffer,
+                       ring_buffer_read_prepare(iter.array_buffer->buffer,
                                                 cpu_file, GFP_ATOMIC);
                ring_buffer_read_start(iter.buffer_iter[cpu_file]);
                tracing_iter_reset(&iter, cpu_file);
@@ -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))
@@ -89,10 +81,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 +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.array_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.array_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;
 }