summaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2008-11-11 05:07:30 +0100
committerIngo Molnar <mingo@elte.hu>2008-11-11 09:40:29 +0100
commit5aa1ba6a6c710e747838a22d798ac97a8b248745 (patch)
tree29a0e0bfdad1a5674667dda1236099952dbf41cb /kernel/trace/trace.c
parentMerge branch 'tracing/urgent' into tracing/ftrace (diff)
downloadlinux-5aa1ba6a6c710e747838a22d798ac97a8b248745.tar.xz
linux-5aa1ba6a6c710e747838a22d798ac97a8b248745.zip
ftrace: prevent ftrace_special from recursion
Impact: stop ftrace_special from recursion The ftrace_special is used to help debug areas of the kernel. Because of this, if it is put in certain locations, the fact that it allows recursion can become a problem if the kernel developer using does not realize that. This patch changes ftrace_special to not allow recursion into itself to make it more robust. It also changes from preempt disable interrupts disable to prevent any loss of trace entries. Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 0c22fe2d43a7..216bbe7547a4 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -960,6 +960,7 @@ ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3)
{
struct trace_array *tr = &global_trace;
struct trace_array_cpu *data;
+ unsigned long flags;
int cpu;
int pc;
@@ -967,14 +968,15 @@ ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3)
return;
pc = preempt_count();
- preempt_disable_notrace();
+ local_irq_save(flags);
cpu = raw_smp_processor_id();
data = tr->data[cpu];
- if (likely(!atomic_read(&data->disabled)))
+ if (likely(atomic_inc_return(&data->disabled) == 1))
ftrace_trace_special(tr, data, arg1, arg2, arg3, pc);
- preempt_enable_notrace();
+ atomic_dec(&data->disabled);
+ local_irq_restore(flags);
}
#ifdef CONFIG_FUNCTION_TRACER