Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad71d889 authored by Steven Rostedt (Red Hat)'s avatar Steven Rostedt (Red Hat) Committed by Steven Rostedt
Browse files

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: default avatarLuis Claudio R. Goncalves <lclaudio@uudg.org>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 317ddd25
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -2430,6 +2430,13 @@ The following commands are supported:
   echo '!schedule:disable_event:sched:sched_switch' > \
   echo '!schedule:disable_event:sched:sched_switch' > \
   	 set_ftrace_filter
   	 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
trace_pipe
----------
----------


+54 −5
Original line number Original line Diff line number Diff line
@@ -290,6 +290,13 @@ ftrace_stacktrace_count(unsigned long ip, unsigned long parent_ip, void **data)
		trace_dump_stack(STACK_SKIP);
		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
static int
ftrace_probe_print(const char *name, struct seq_file *m,
ftrace_probe_print(const char *name, struct seq_file *m,
		   unsigned long ip, void *data)
		   unsigned long ip, void *data)
@@ -327,6 +334,13 @@ ftrace_stacktrace_print(struct seq_file *m, unsigned long ip,
	return ftrace_probe_print("stacktrace", m, ip, data);
	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 = {
static struct ftrace_probe_ops traceon_count_probe_ops = {
	.func			= ftrace_traceon_count,
	.func			= ftrace_traceon_count,
	.print			= ftrace_traceon_print,
	.print			= ftrace_traceon_print,
@@ -342,6 +356,11 @@ static struct ftrace_probe_ops stacktrace_count_probe_ops = {
	.print			= ftrace_stacktrace_print,
	.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 = {
static struct ftrace_probe_ops traceon_probe_ops = {
	.func			= ftrace_traceon,
	.func			= ftrace_traceon,
	.print			= ftrace_traceon_print,
	.print			= ftrace_traceon_print,
@@ -425,6 +444,19 @@ ftrace_stacktrace_callback(struct ftrace_hash *hash,
					   param, enable);
					   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 = {
static struct ftrace_func_command ftrace_traceon_cmd = {
	.name			= "traceon",
	.name			= "traceon",
	.func			= ftrace_trace_onoff_callback,
	.func			= ftrace_trace_onoff_callback,
@@ -440,6 +472,11 @@ static struct ftrace_func_command ftrace_stacktrace_cmd = {
	.func			= ftrace_stacktrace_callback,
	.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)
static int __init init_func_cmd_traceon(void)
{
{
	int ret;
	int ret;
@@ -450,13 +487,25 @@ static int __init init_func_cmd_traceon(void)


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


	ret = register_ftrace_command(&ftrace_stacktrace_cmd);
	ret = register_ftrace_command(&ftrace_stacktrace_cmd);
	if (ret) {
	if (ret)
		unregister_ftrace_command(&ftrace_traceoff_cmd);
		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);
	unregister_ftrace_command(&ftrace_traceon_cmd);
	}
 out_free_traceoff:
	unregister_ftrace_command(&ftrace_traceoff_cmd);

	return ret;
	return ret;
}
}
#else
#else