aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2013-04-30 15:46:14 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-06-11 18:38:46 -0400
commitad71d889b88055e61e3970a6744a271a51a94f42 (patch)
tree716f6e043847000a82449270e3b2d5dcdc9c4f79 /kernel
parent317ddd256b9c24b0d78fa8018f80f1e495481a10 (diff)
tracing: Add function probe to trigger a ftrace dump to console
Add the "dump" command to have the ftrace buffer dumped to console if a function is hit. This is useful when debugging a tripple fault, where you have an idea of a function that is called just before the tripple fault occurs, and can tell ftrace to dump its content out to the console before it continues. Format is: <function>:dump echo 'bad_address:dump' > /debug/tracing/set_ftrace_filter To remove this: echo '!bad_address:dump' > /debug/tracing/set_ftrace_filter Requested-by: Luis Claudio R. Goncalves <lclaudio@uudg.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace_functions.c59
1 files changed, 54 insertions, 5 deletions
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index c4d6d7191988..d7c8719734b8 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -290,6 +290,13 @@ ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, void **data)
290 trace_dump_stack(STACK_SKIP); 290 trace_dump_stack(STACK_SKIP);
291} 291}
292 292
293static void
294ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, void **data)
295{
296 if (update_count(data))
297 ftrace_dump(DUMP_ALL);
298}
299
293static int 300static int
294ftrace_probe_print(const char *name, struct seq_file *m, 301ftrace_probe_print(const char *name, struct seq_file *m,
295 unsigned long ip, void *data) 302 unsigned long ip, void *data)
@@ -327,6 +334,13 @@ ftrace_stacktrace_print(struct seq_file *m, unsigned long ip,
327 return ftrace_probe_print("stacktrace", m, ip, data); 334 return ftrace_probe_print("stacktrace", m, ip, data);
328} 335}
329 336
337static int
338ftrace_dump_print(struct seq_file *m, unsigned long ip,
339 struct ftrace_probe_ops *ops, void *data)
340{
341 return ftrace_probe_print("dump", m, ip, data);
342}
343
330static struct ftrace_probe_ops traceon_count_probe_ops = { 344static struct ftrace_probe_ops traceon_count_probe_ops = {
331 .func = ftrace_traceon_count, 345 .func = ftrace_traceon_count,
332 .print = ftrace_traceon_print, 346 .print = ftrace_traceon_print,
@@ -342,6 +356,11 @@ static struct ftrace_probe_ops stacktrace_count_probe_ops = {
342 .print = ftrace_stacktrace_print, 356 .print = ftrace_stacktrace_print,
343}; 357};
344 358
359static struct ftrace_probe_ops dump_probe_ops = {
360 .func = ftrace_dump_probe,
361 .print = ftrace_dump_print,
362};
363
345static struct ftrace_probe_ops traceon_probe_ops = { 364static struct ftrace_probe_ops traceon_probe_ops = {
346 .func = ftrace_traceon, 365 .func = ftrace_traceon,
347 .print = ftrace_traceon_print, 366 .print = ftrace_traceon_print,
@@ -425,6 +444,19 @@ ftrace_stacktrace_callback(struct ftrace_hash *hash,
425 param, enable); 444 param, enable);
426} 445}
427 446
447static int
448ftrace_dump_callback(struct ftrace_hash *hash,
449 char *glob, char *cmd, char *param, int enable)
450{
451 struct ftrace_probe_ops *ops;
452
453 ops = &dump_probe_ops;
454
455 /* Only dump once. */
456 return ftrace_trace_probe_callback(ops, hash, glob, cmd,
457 "1", enable);
458}
459
428static struct ftrace_func_command ftrace_traceon_cmd = { 460static struct ftrace_func_command ftrace_traceon_cmd = {
429 .name = "traceon", 461 .name = "traceon",
430 .func = ftrace_trace_onoff_callback, 462 .func = ftrace_trace_onoff_callback,
@@ -440,6 +472,11 @@ static struct ftrace_func_command ftrace_stacktrace_cmd = {
440 .func = ftrace_stacktrace_callback, 472 .func = ftrace_stacktrace_callback,
441}; 473};
442 474
475static struct ftrace_func_command ftrace_dump_cmd = {
476 .name = "dump",
477 .func = ftrace_dump_callback,
478};
479
443static int __init init_func_cmd_traceon(void) 480static int __init init_func_cmd_traceon(void)
444{ 481{
445 int ret; 482 int ret;
@@ -450,13 +487,25 @@ static int __init init_func_cmd_traceon(void)
450 487
451 ret = register_ftrace_command(&ftrace_traceon_cmd); 488 ret = register_ftrace_command(&ftrace_traceon_cmd);
452 if (ret) 489 if (ret)
453 unregister_ftrace_command(&ftrace_traceoff_cmd); 490 goto out_free_traceoff;
454 491
455 ret = register_ftrace_command(&ftrace_stacktrace_cmd); 492 ret = register_ftrace_command(&ftrace_stacktrace_cmd);
456 if (ret) { 493 if (ret)
457 unregister_ftrace_command(&ftrace_traceoff_cmd); 494 goto out_free_traceon;
458 unregister_ftrace_command(&ftrace_traceon_cmd); 495
459 } 496 ret = register_ftrace_command(&ftrace_dump_cmd);
497 if (ret)
498 goto out_free_stacktrace;
499
500 return 0;
501
502 out_free_stacktrace:
503 unregister_ftrace_command(&ftrace_stacktrace_cmd);
504 out_free_traceon:
505 unregister_ftrace_command(&ftrace_traceon_cmd);
506 out_free_traceoff:
507 unregister_ftrace_command(&ftrace_traceoff_cmd);
508
460 return ret; 509 return ret;
461} 510}
462#else 511#else