tracing: Print max callstack on stacktrace bug
[cascardo/linux.git] / kernel / trace / trace_stack.c
index 5aa9a5b..8a4e5cb 100644 (file)
@@ -51,11 +51,33 @@ static DEFINE_MUTEX(stack_sysctl_mutex);
 int stack_tracer_enabled;
 static int last_stack_tracer_enabled;
 
+static inline void print_max_stack(void)
+{
+       long i;
+       int size;
+
+       pr_emerg("        Depth    Size   Location    (%d entries)\n"
+                          "        -----    ----   --------\n",
+                          max_stack_trace.nr_entries - 1);
+
+       for (i = 0; i < max_stack_trace.nr_entries; i++) {
+               if (stack_dump_trace[i] == ULONG_MAX)
+                       break;
+               if (i+1 == max_stack_trace.nr_entries ||
+                               stack_dump_trace[i+1] == ULONG_MAX)
+                       size = stack_dump_index[i];
+               else
+                       size = stack_dump_index[i] - stack_dump_index[i+1];
+
+               pr_emerg("%3ld) %8d   %5d   %pS\n", i, stack_dump_index[i],
+                               size, (void *)stack_dump_trace[i]);
+       }
+}
+
 static inline void
 check_stack(unsigned long ip, unsigned long *stack)
 {
-       unsigned long this_size, flags;
-       unsigned long *p, *top, *start;
+       unsigned long this_size, flags; unsigned long *p, *top, *start;
        static int tracer_frame;
        int frame_size = ACCESS_ONCE(tracer_frame);
        int i;
@@ -149,8 +171,12 @@ check_stack(unsigned long ip, unsigned long *stack)
                        i++;
        }
 
-       BUG_ON(current != &init_task &&
-               *(end_of_stack(current)) != STACK_END_MAGIC);
+       if ((current != &init_task &&
+               *(end_of_stack(current)) != STACK_END_MAGIC)) {
+               print_max_stack();
+               BUG();
+       }
+
  out:
        arch_spin_unlock(&max_stack_lock);
        local_irq_restore(flags);