aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-04-17 16:13:55 -0400
committerSteven Rostedt <rostedt@goodmis.org>2009-04-17 16:21:35 -0400
commit3189cdb31622f4e40688ce5a6fc5d940b42bc805 (patch)
tree89f370c0079281c55f37230c17951514c1b508c9 /kernel/trace/trace.c
parent261842b7c9099f56de2eb969c8ad65402d68e00e (diff)
tracing: protect trace_printk from recursion
trace_printk can be called from any context, including NMIs. If this happens, then we must test for for recursion before grabbing any spinlocks. This patch prevents trace_printk from being called recursively. [ Impact: prevent hard lockup in lockdep event tracer ] Cc: Peter Zijlstra <peterz@infradead.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 183d788038e8..b9a3adce9221 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1259,6 +1259,7 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
1259 struct trace_array_cpu *data; 1259 struct trace_array_cpu *data;
1260 struct bprint_entry *entry; 1260 struct bprint_entry *entry;
1261 unsigned long flags; 1261 unsigned long flags;
1262 int disable;
1262 int resched; 1263 int resched;
1263 int cpu, len = 0, size, pc; 1264 int cpu, len = 0, size, pc;
1264 1265
@@ -1273,7 +1274,8 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
1273 cpu = raw_smp_processor_id(); 1274 cpu = raw_smp_processor_id();
1274 data = tr->data[cpu]; 1275 data = tr->data[cpu];
1275 1276
1276 if (unlikely(atomic_read(&data->disabled))) 1277 disable = atomic_inc_return(&data->disabled);
1278 if (unlikely(disable != 1))
1277 goto out; 1279 goto out;
1278 1280
1279 /* Lockdep uses trace_printk for lock tracing */ 1281 /* Lockdep uses trace_printk for lock tracing */
@@ -1301,6 +1303,7 @@ out_unlock:
1301 local_irq_restore(flags); 1303 local_irq_restore(flags);
1302 1304
1303out: 1305out:
1306 atomic_dec_return(&data->disabled);
1304 ftrace_preempt_enable(resched); 1307 ftrace_preempt_enable(resched);
1305 unpause_graph_tracing(); 1308 unpause_graph_tracing();
1306 1309
@@ -1320,6 +1323,7 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
1320 int cpu, len = 0, size, pc; 1323 int cpu, len = 0, size, pc;
1321 struct print_entry *entry; 1324 struct print_entry *entry;
1322 unsigned long irq_flags; 1325 unsigned long irq_flags;
1326 int disable;
1323 1327
1324 if (tracing_disabled || tracing_selftest_running) 1328 if (tracing_disabled || tracing_selftest_running)
1325 return 0; 1329 return 0;
@@ -1329,7 +1333,8 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
1329 cpu = raw_smp_processor_id(); 1333 cpu = raw_smp_processor_id();
1330 data = tr->data[cpu]; 1334 data = tr->data[cpu];
1331 1335
1332 if (unlikely(atomic_read(&data->disabled))) 1336 disable = atomic_inc_return(&data->disabled);
1337 if (unlikely(disable != 1))
1333 goto out; 1338 goto out;
1334 1339
1335 pause_graph_tracing(); 1340 pause_graph_tracing();
@@ -1357,6 +1362,7 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
1357 raw_local_irq_restore(irq_flags); 1362 raw_local_irq_restore(irq_flags);
1358 unpause_graph_tracing(); 1363 unpause_graph_tracing();
1359 out: 1364 out:
1365 atomic_dec_return(&data->disabled);
1360 preempt_enable_notrace(); 1366 preempt_enable_notrace();
1361 1367
1362 return len; 1368 return len;