aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_selftest.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-03-22 00:04:35 -0400
committerIngo Molnar <mingo@elte.hu>2009-03-22 09:06:40 -0400
commitcf586b61f80229491127d3c57c06ed93c9f530d3 (patch)
tree3f5e0d9429f32b8ad4f53104a260c8dff349cd9b /kernel/trace/trace_selftest.c
parentac199db0189c091f2863312061c0575937f68810 (diff)
tracing/function-graph-tracer: prevent hangs during self-tests
Impact: detect tracing related hangs Sometimes, with some configs, the function graph tracer can make the timer interrupt too much slow, hanging the kernel in an endless loop of timer interrupts servicing. As suggested by Ingo, this patch brings a watchdog which stops the selftest after a defined number of functions traced, definitely disabling this tracer. For those who want to debug the cause of the function graph trace hang, you can pass the ftrace_dump_on_oops kernel parameter to dump the traces after this hang detection. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <1237694675-23509-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace_selftest.c')
-rw-r--r--kernel/trace/trace_selftest.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 38856ba78a92..b56dcf7d3566 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -248,6 +248,28 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
248 248
249 249
250#ifdef CONFIG_FUNCTION_GRAPH_TRACER 250#ifdef CONFIG_FUNCTION_GRAPH_TRACER
251
252/* Maximum number of functions to trace before diagnosing a hang */
253#define GRAPH_MAX_FUNC_TEST 100000000
254
255static void __ftrace_dump(bool disable_tracing);
256static unsigned int graph_hang_thresh;
257
258/* Wrap the real function entry probe to avoid possible hanging */
259static int trace_graph_entry_watchdog(struct ftrace_graph_ent *trace)
260{
261 /* This is harmlessly racy, we want to approximately detect a hang */
262 if (unlikely(++graph_hang_thresh > GRAPH_MAX_FUNC_TEST)) {
263 ftrace_graph_stop();
264 printk(KERN_WARNING "BUG: Function graph tracer hang!\n");
265 if (ftrace_dump_on_oops)
266 __ftrace_dump(false);
267 return 0;
268 }
269
270 return trace_graph_entry(trace);
271}
272
251/* 273/*
252 * Pretty much the same than for the function tracer from which the selftest 274 * Pretty much the same than for the function tracer from which the selftest
253 * has been borrowed. 275 * has been borrowed.
@@ -259,15 +281,29 @@ trace_selftest_startup_function_graph(struct tracer *trace,
259 int ret; 281 int ret;
260 unsigned long count; 282 unsigned long count;
261 283
262 ret = tracer_init(trace, tr); 284 /*
285 * Simulate the init() callback but we attach a watchdog callback
286 * to detect and recover from possible hangs
287 */
288 tracing_reset_online_cpus(tr);
289 ret = register_ftrace_graph(&trace_graph_return,
290 &trace_graph_entry_watchdog);
263 if (ret) { 291 if (ret) {
264 warn_failed_init_tracer(trace, ret); 292 warn_failed_init_tracer(trace, ret);
265 goto out; 293 goto out;
266 } 294 }
295 tracing_start_cmdline_record();
267 296
268 /* Sleep for a 1/10 of a second */ 297 /* Sleep for a 1/10 of a second */
269 msleep(100); 298 msleep(100);
270 299
300 /* Have we just recovered from a hang? */
301 if (graph_hang_thresh > GRAPH_MAX_FUNC_TEST) {
302 trace->reset(tr);
303 ret = -1;
304 goto out;
305 }
306
271 tracing_stop(); 307 tracing_stop();
272 308
273 /* check the trace buffer */ 309 /* check the trace buffer */