summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-10-23 12:24:33 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2015-10-23 12:24:33 +0300
commit8a990fb47b4c93653745512eca7d2d210678e6c1 (patch)
tree1963b538d2b7cb7d1f2daa2231dc78de3a5c6368
parent0122835a020a9f5c007b3a49ea9b5f1ac68fc7c7 (diff)
parent1904be1b6bb92058c8e00063dd59df2df294e258 (diff)
downloadlinux-8a990fb47b4c93653745512eca7d2d210678e6c1.tar.xz
Merge tag 'trace-fixes-v4.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing fixes from Steven Rostedt: "Running tests on other changes, the system locked up due to lots of warnings. It was caused by the stack tracer triggering a warning about using rcu_dereference() when RCU was not watching. This can happen due to the fact that the stack tracer uses the function tracer to check each function, and there are functions that may be called and traced when RCU stopped watching. Namely when a function is called just before going idle or to userspace and after RCU stopped watching that current CPU. The first patch makes sure that RCU is watching when the stack tracer uses RCU. The second patch is to make sure that the stack tracer does not get called by functions in NMI, as it's not NMI safe" * tag 'trace-fixes-v4.3-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: tracing: Do not allow stack_tracer to record stack in NMI tracing: Have stack tracer force RCU to be watching
-rw-r--r--kernel/trace/trace_stack.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index b746399ab59c..8abf1ba18085 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -85,9 +85,19 @@ check_stack(unsigned long ip, unsigned long *stack)
if (!object_is_on_stack(stack))
return;
+ /* Can't do this from NMI context (can cause deadlocks) */
+ if (in_nmi())
+ return;
+
local_irq_save(flags);
arch_spin_lock(&max_stack_lock);
+ /*
+ * RCU may not be watching, make it see us.
+ * The stack trace code uses rcu_sched.
+ */
+ rcu_irq_enter();
+
/* In case another CPU set the tracer_frame on us */
if (unlikely(!frame_size))
this_size -= tracer_frame;
@@ -169,6 +179,7 @@ check_stack(unsigned long ip, unsigned long *stack)
}
out:
+ rcu_irq_exit();
arch_spin_unlock(&max_stack_lock);
local_irq_restore(flags);
}