aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_selftest.c
diff options
context:
space:
mode:
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 */