diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-04-17 16:13:55 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-04-17 16:21:35 -0400 |
commit | 3189cdb31622f4e40688ce5a6fc5d940b42bc805 (patch) | |
tree | 89f370c0079281c55f37230c17951514c1b508c9 /kernel/trace/trace.c | |
parent | 261842b7c9099f56de2eb969c8ad65402d68e00e (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.c | 10 |
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 | ||
1303 | out: | 1305 | out: |
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; |