summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/trace/ftrace.txt6
-rw-r--r--kernel/trace/trace_functions.c44
2 files changed, 50 insertions, 0 deletions
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index cc9ec57e157c..b937c6e2163c 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -2437,6 +2437,12 @@ The following commands are supported:
is hit. Perhaps its a function that is called before a tripple
fault happens and does not allow you to get a regular dump.
+- cpudump
+ When the function is hit, it will dump the contents of the ftrace
+ ring buffer for the current CPU to the console. Unlike the "dump"
+ command, it only prints out the contents of the ring buffer for the
+ CPU that executed the function that triggered the dump.
+
trace_pipe
----------
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index d7c8719734b8..b863f93b30f3 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -297,6 +297,14 @@ ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, void **data)
ftrace_dump(DUMP_ALL);
}
+/* Only dump the current CPU buffer. */
+static void
+ftrace_cpudump_probe(unsigned long ip, unsigned long parent_ip, void **data)
+{
+ if (update_count(data))
+ ftrace_dump(DUMP_ORIG);
+}
+
static int
ftrace_probe_print(const char *name, struct seq_file *m,
unsigned long ip, void *data)
@@ -341,6 +349,13 @@ ftrace_dump_print(struct seq_file *m, unsigned long ip,
return ftrace_probe_print("dump", m, ip, data);
}
+static int
+ftrace_cpudump_print(struct seq_file *m, unsigned long ip,
+ struct ftrace_probe_ops *ops, void *data)
+{
+ return ftrace_probe_print("cpudump", m, ip, data);
+}
+
static struct ftrace_probe_ops traceon_count_probe_ops = {
.func = ftrace_traceon_count,
.print = ftrace_traceon_print,
@@ -361,6 +376,11 @@ static struct ftrace_probe_ops dump_probe_ops = {
.print = ftrace_dump_print,
};
+static struct ftrace_probe_ops cpudump_probe_ops = {
+ .func = ftrace_cpudump_probe,
+ .print = ftrace_cpudump_print,
+};
+
static struct ftrace_probe_ops traceon_probe_ops = {
.func = ftrace_traceon,
.print = ftrace_traceon_print,
@@ -457,6 +477,19 @@ ftrace_dump_callback(struct ftrace_hash *hash,
"1", enable);
}
+static int
+ftrace_cpudump_callback(struct ftrace_hash *hash,
+ char *glob, char *cmd, char *param, int enable)
+{
+ struct ftrace_probe_ops *ops;
+
+ ops = &cpudump_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,
@@ -477,6 +510,11 @@ static struct ftrace_func_command ftrace_dump_cmd = {
.func = ftrace_dump_callback,
};
+static struct ftrace_func_command ftrace_cpudump_cmd = {
+ .name = "cpudump",
+ .func = ftrace_cpudump_callback,
+};
+
static int __init init_func_cmd_traceon(void)
{
int ret;
@@ -497,8 +535,14 @@ static int __init init_func_cmd_traceon(void)
if (ret)
goto out_free_stacktrace;
+ ret = register_ftrace_command(&ftrace_cpudump_cmd);
+ if (ret)
+ goto out_free_dump;
+
return 0;
+ out_free_dump:
+ unregister_ftrace_command(&ftrace_dump_cmd);
out_free_stacktrace:
unregister_ftrace_command(&ftrace_stacktrace_cmd);
out_free_traceon: