aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-04-16 21:41:52 -0400
committerSteven Rostedt <rostedt@goodmis.org>2009-04-17 16:21:32 -0400
commit261842b7c9099f56de2eb969c8ad65402d68e00e (patch)
tree6cdf0b4b5ad188294da67520dc9579a0c67940ac /include/linux
parent12acd473d45cf2e40de3782cb2de712e5cd4d715 (diff)
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>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/ftrace.h7
-rw-r--r--include/linux/init_task.h1
-rw-r--r--include/linux/sched.h4
3 files changed, 11 insertions, 1 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 97c83e1bc589..39b95c56587e 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -488,8 +488,15 @@ static inline int test_tsk_trace_graph(struct task_struct *tsk)
488 488
489extern int ftrace_dump_on_oops; 489extern int ftrace_dump_on_oops;
490 490
491#ifdef CONFIG_PREEMPT
492#define INIT_TRACE_RECURSION .trace_recursion = 0,
493#endif
494
491#endif /* CONFIG_TRACING */ 495#endif /* CONFIG_TRACING */
492 496
497#ifndef INIT_TRACE_RECURSION
498#define INIT_TRACE_RECURSION
499#endif
493 500
494#ifdef CONFIG_HW_BRANCH_TRACER 501#ifdef CONFIG_HW_BRANCH_TRACER
495 502
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index dcfb93337e9a..6fc218529863 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -187,6 +187,7 @@ extern struct cred init_cred;
187 INIT_TRACE_IRQFLAGS \ 187 INIT_TRACE_IRQFLAGS \
188 INIT_LOCKDEP \ 188 INIT_LOCKDEP \
189 INIT_FTRACE_GRAPH \ 189 INIT_FTRACE_GRAPH \
190 INIT_TRACE_RECURSION \
190} 191}
191 192
192 193
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b4c38bc8049c..7ede5e490913 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1428,7 +1428,9 @@ struct task_struct {
1428#ifdef CONFIG_TRACING 1428#ifdef CONFIG_TRACING
1429 /* state flags for use by tracers */ 1429 /* state flags for use by tracers */
1430 unsigned long trace; 1430 unsigned long trace;
1431#endif 1431 /* bitmask of trace recursion */
1432 unsigned long trace_recursion;
1433#endif /* CONFIG_TRACING */
1432}; 1434};
1433 1435
1434/* Future-safe accessor for struct task_struct's cpus_allowed. */ 1436/* Future-safe accessor for struct task_struct's cpus_allowed. */