Skip to content

Commit

Permalink
tracing: Add function probe to trigger a ftrace dump to console
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steven Rostedt (Red Hat) committed Jun 11, 2013
1 parent 317ddd2 commit ad71d88
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 5 deletions.
7 changes: 7 additions & 0 deletions Documentation/trace/ftrace.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2430,6 +2430,13 @@ The following commands are supported:
echo '!schedule:disable_event:sched:sched_switch' > \
set_ftrace_filter

- dump
When the function is hit, it will dump the contents of the ftrace
ring buffer to the console. This is useful if you need to debug
something, and want to dump the trace when a certain function
is hit. Perhaps its a function that is called before a tripple
fault happens and does not allow you to get a regular dump.

trace_pipe
----------

Expand Down
59 changes: 54 additions & 5 deletions kernel/trace/trace_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,13 @@ ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, void **data)
trace_dump_stack(STACK_SKIP);
}

static void
ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, void **data)
{
if (update_count(data))
ftrace_dump(DUMP_ALL);
}

static int
ftrace_probe_print(const char *name, struct seq_file *m,
unsigned long ip, void *data)
Expand Down Expand Up @@ -327,6 +334,13 @@ ftrace_stacktrace_print(struct seq_file *m, unsigned long ip,
return ftrace_probe_print("stacktrace", m, ip, data);
}

static int
ftrace_dump_print(struct seq_file *m, unsigned long ip,
struct ftrace_probe_ops *ops, void *data)
{
return ftrace_probe_print("dump", m, ip, data);
}

static struct ftrace_probe_ops traceon_count_probe_ops = {
.func = ftrace_traceon_count,
.print = ftrace_traceon_print,
Expand All @@ -342,6 +356,11 @@ static struct ftrace_probe_ops stacktrace_count_probe_ops = {
.print = ftrace_stacktrace_print,
};

static struct ftrace_probe_ops dump_probe_ops = {
.func = ftrace_dump_probe,
.print = ftrace_dump_print,
};

static struct ftrace_probe_ops traceon_probe_ops = {
.func = ftrace_traceon,
.print = ftrace_traceon_print,
Expand Down Expand Up @@ -425,6 +444,19 @@ ftrace_stacktrace_callback(struct ftrace_hash *hash,
param, enable);
}

static int
ftrace_dump_callback(struct ftrace_hash *hash,
char *glob, char *cmd, char *param, int enable)
{
struct ftrace_probe_ops *ops;

ops = &dump_probe_ops;

/* Only dump once. */
return ftrace_trace_probe_callback(ops, hash, glob, cmd,
"1", enable);
}

static struct ftrace_func_command ftrace_traceon_cmd = {
.name = "traceon",
.func = ftrace_trace_onoff_callback,
Expand All @@ -440,6 +472,11 @@ static struct ftrace_func_command ftrace_stacktrace_cmd = {
.func = ftrace_stacktrace_callback,
};

static struct ftrace_func_command ftrace_dump_cmd = {
.name = "dump",
.func = ftrace_dump_callback,
};

static int __init init_func_cmd_traceon(void)
{
int ret;
Expand All @@ -450,13 +487,25 @@ static int __init init_func_cmd_traceon(void)

ret = register_ftrace_command(&ftrace_traceon_cmd);
if (ret)
unregister_ftrace_command(&ftrace_traceoff_cmd);
goto out_free_traceoff;

ret = register_ftrace_command(&ftrace_stacktrace_cmd);
if (ret) {
unregister_ftrace_command(&ftrace_traceoff_cmd);
unregister_ftrace_command(&ftrace_traceon_cmd);
}
if (ret)
goto out_free_traceon;

ret = register_ftrace_command(&ftrace_dump_cmd);
if (ret)
goto out_free_stacktrace;

return 0;

out_free_stacktrace:
unregister_ftrace_command(&ftrace_stacktrace_cmd);
out_free_traceon:
unregister_ftrace_command(&ftrace_traceon_cmd);
out_free_traceoff:
unregister_ftrace_command(&ftrace_traceoff_cmd);

return ret;
}
#else
Expand Down

0 comments on commit ad71d88

Please sign in to comment.