tracing: add same level recursion detection
authorSteven Rostedt <srostedt@redhat.com>
Fri, 17 Apr 2009 01:41:52 +0000 (21:41 -0400)
committerSteven Rostedt <rostedt@goodmis.org>
Fri, 17 Apr 2009 20:21:32 +0000 (16:21 -0400)
commit261842b7c9099f56de2eb969c8ad65402d68e00e
tree6cdf0b4b5ad188294da67520dc9579a0c67940ac
parent12acd473d45cf2e40de3782cb2de712e5cd4d715
tracing: add same level recursion detection

The tracing infrastructure allows for recursion. That is, an interrupt
may interrupt the act of tracing an event, and that interrupt may very well
perform its own trace. This is a recursive trace, and is fine to do.

The problem arises when there is a bug, and the utility doing the trace
calls something that recurses back into the tracer. This recursion is not
caused by an external event like an interrupt, but by code that is not
expected to recurse. The result could be a lockup.

This patch adds a bitmask to the task structure that keeps track
of the trace recursion. To find the interrupt depth, the following
algorithm is used:

  level = hardirq_count() + softirq_count() + in_nmi;

Here, level will be the depth of interrutps and softirqs, and even handles
the nmi. Then the corresponding bit is set in the recursion bitmask.
If the bit was already set, we know we had a recursion at the same level
and we warn about it and fail the writing to the buffer.

After the data has been committed to the buffer, we clear the bit.
No atomics are needed. The only races are with interrupts and they reset
the bitmask before returning anywy.

[ Impact: detect same irq level trace recursion ]

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
include/linux/ftrace.h
include/linux/init_task.h
include/linux/sched.h
kernel/trace/ring_buffer.c