x86: don't save unreliable stack trace entries
[sfrench/cifs-2.6.git] / arch / x86 / kernel / stacktrace.c
index 413e527cdeb97394bbccb245d182338b463fcde4..c28c342c162f0a90d3ad6e50ba0fb1d5ecd132a7 100644 (file)
@@ -22,9 +22,27 @@ static int save_stack_stack(void *data, char *name)
        return -1;
 }
 
-static void save_stack_address(void *data, unsigned long addr)
+static void save_stack_address(void *data, unsigned long addr, int reliable)
+{
+       struct stack_trace *trace = data;
+       if (!reliable)
+               return;
+       if (trace->skip > 0) {
+               trace->skip--;
+               return;
+       }
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = addr;
+}
+
+static void
+save_stack_address_nosched(void *data, unsigned long addr, int reliable)
 {
        struct stack_trace *trace = (struct stack_trace *)data;
+       if (!reliable)
+               return;
+       if (in_sched_functions(addr))
+               return;
        if (trace->skip > 0) {
                trace->skip--;
                return;
@@ -33,20 +51,33 @@ static void save_stack_address(void *data, unsigned long addr)
                trace->entries[trace->nr_entries++] = addr;
 }
 
-static struct stacktrace_ops save_stack_ops = {
+static const struct stacktrace_ops save_stack_ops = {
        .warning = save_stack_warning,
        .warning_symbol = save_stack_warning_symbol,
        .stack = save_stack_stack,
        .address = save_stack_address,
 };
 
+static const struct stacktrace_ops save_stack_ops_nosched = {
+       .warning = save_stack_warning,
+       .warning_symbol = save_stack_warning_symbol,
+       .stack = save_stack_stack,
+       .address = save_stack_address_nosched,
+};
+
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
  */
 void save_stack_trace(struct stack_trace *trace)
 {
-       dump_trace(current, NULL, NULL, &save_stack_ops, trace);
+       dump_trace(current, NULL, NULL, 0, &save_stack_ops, trace);
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+       dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace);
        if (trace->nr_entries < trace->max_entries)
                trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
-EXPORT_SYMBOL(save_stack_trace);