]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf ftrace: Use process/session specific trace settings
authorThomas Richter <tmricht@linux.ibm.com>
Tue, 20 May 2025 09:37:26 +0000 (11:37 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 20 May 2025 16:11:09 +0000 (13:11 -0300)
Executing 'perf ftrace' commands 'ftrace', 'profile' and 'latency' leave
tracing disabled as can seen in this output:

 # echo 1 > /sys/kernel/debug/tracing/tracing_on
 # cat /sys/kernel/debug/tracing/tracing_on
 1
 # perf ftrace trace --graph-opts depth=5 sleep 0.1 > /dev/null
 # cat /sys/kernel/debug/tracing/tracing_on
 0
 #

The 'tracing_on' file is not restored to its value before the command.

To fix that this patch uses the .../tracing/instances/XXX subdirectory
feature.

Each 'perf ftrace' invocation creates its own session/process
specific subdirectory and does not change the global state
in the .../tracing directory itself.

Use rmdir(../tracing/instances/dir) to stop process/session specific
tracing and delete all process/session specific setings.

Reported-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Suggested-by: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Link: https://lore.kernel.org/r/20250520093726.2009696-1-tmricht@linux.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-ftrace.c

index 7caa18d5ffc382381ced75e34b505a300c5728a1..bba36ebc2aa7f2908ebd18885f0b0cbf66ec1142 100644 (file)
@@ -19,6 +19,7 @@
 #include <ctype.h>
 #include <linux/capability.h>
 #include <linux/string.h>
+#include <sys/stat.h>
 
 #include "debug.h"
 #include <subcmd/pager.h>
@@ -45,6 +46,8 @@ static volatile sig_atomic_t done;
 
 static struct stats latency_stats;  /* for tracepoints */
 
+static char tracing_instance[PATH_MAX];        /* Trace instance directory */
+
 static void sig_handler(int sig __maybe_unused)
 {
        done = true;
@@ -100,6 +103,34 @@ static bool is_ftrace_supported(void)
        return supported;
 }
 
+/*
+ * Wrapper to test if a file in directory .../tracing/instances/XXX
+ * exists. If so return the .../tracing/instances/XXX file for use.
+ * Otherwise the file exists only in directory .../tracing and
+ * is applicable to all instances, for example file available_filter_functions.
+ * Return that file name in this case.
+ *
+ * This functions works similar to get_tracing_file() and expects its caller
+ * to free the returned file name.
+ *
+ * The global variable tracing_instance is set in init_tracing_instance()
+ * called at the  beginning to a process specific tracing subdirectory.
+ */
+static char *get_tracing_instance_file(const char *name)
+{
+       char *file;
+
+       if (asprintf(&file, "%s/%s", tracing_instance, name) < 0)
+               return NULL;
+
+       if (!access(file, F_OK))
+               return file;
+
+       free(file);
+       file = get_tracing_file(name);
+       return file;
+}
+
 static int __write_tracing_file(const char *name, const char *val, bool append)
 {
        char *file;
@@ -109,7 +140,7 @@ static int __write_tracing_file(const char *name, const char *val, bool append)
        char errbuf[512];
        char *val_copy;
 
-       file = get_tracing_file(name);
+       file = get_tracing_instance_file(name);
        if (!file) {
                pr_debug("cannot get tracing file: %s\n", name);
                return -1;
@@ -167,7 +198,7 @@ static int read_tracing_file_to_stdout(const char *name)
        int fd;
        int ret = -1;
 
-       file = get_tracing_file(name);
+       file = get_tracing_instance_file(name);
        if (!file) {
                pr_debug("cannot get tracing file: %s\n", name);
                return -1;
@@ -209,7 +240,7 @@ static int read_tracing_file_by_line(const char *name,
        char *file;
        FILE *fp;
 
-       file = get_tracing_file(name);
+       file = get_tracing_instance_file(name);
        if (!file) {
                pr_debug("cannot get tracing file: %s\n", name);
                return -1;
@@ -299,6 +330,39 @@ static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
        return 0;
 }
 
+/* Remove .../tracing/instances/XXX subdirectory created with
+ * init_tracing_instance().
+ */
+static void exit_tracing_instance(void)
+{
+       if (rmdir(tracing_instance))
+               pr_err("failed to delete tracing/instances directory\n");
+}
+
+/* Create subdirectory within .../tracing/instances/XXX to have session
+ * or process specific setup. To delete this setup, simply remove the
+ * subdirectory.
+ */
+static int init_tracing_instance(void)
+{
+       char dirname[] = "instances/perf-ftrace-XXXXXX";
+       char *path;
+
+       path = get_tracing_file(dirname);
+       if (!path)
+               goto error;
+       strncpy(tracing_instance, path, sizeof(tracing_instance) - 1);
+       put_tracing_file(path);
+       path = mkdtemp(tracing_instance);
+       if (!path)
+               goto error;
+       return 0;
+
+error:
+       pr_err("failed to create tracing/instances directory\n");
+       return -1;
+}
+
 static int set_tracing_pid(struct perf_ftrace *ftrace)
 {
        int i;
@@ -629,14 +693,17 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace)
 
        select_tracer(ftrace);
 
+       if (init_tracing_instance() < 0)
+               goto out;
+
        if (reset_tracing_files(ftrace) < 0) {
                pr_err("failed to reset ftrace\n");
-               goto out;
+               goto out_reset;
        }
 
        /* reset ftrace buffer */
        if (write_tracing_file("trace", "0") < 0)
-               goto out;
+               goto out_reset;
 
        if (set_tracing_options(ftrace) < 0)
                goto out_reset;
@@ -648,7 +715,7 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace)
 
        setup_pager();
 
-       trace_file = get_tracing_file("trace_pipe");
+       trace_file = get_tracing_instance_file("trace_pipe");
        if (!trace_file) {
                pr_err("failed to open trace_pipe\n");
                goto out_reset;
@@ -723,7 +790,7 @@ static int __cmd_ftrace(struct perf_ftrace *ftrace)
 out_close_fd:
        close(trace_fd);
 out_reset:
-       reset_tracing_files(ftrace);
+       exit_tracing_instance();
 out:
        return (done && !workload_exec_errno) ? 0 : -1;
 }
@@ -924,6 +991,9 @@ static int prepare_func_latency(struct perf_ftrace *ftrace)
        if (ftrace->target.use_bpf)
                return perf_ftrace__latency_prepare_bpf(ftrace);
 
+       if (init_tracing_instance() < 0)
+               return -1;
+
        if (reset_tracing_files(ftrace) < 0) {
                pr_err("failed to reset ftrace\n");
                return -1;
@@ -942,7 +1012,7 @@ static int prepare_func_latency(struct perf_ftrace *ftrace)
                return -1;
        }
 
-       trace_file = get_tracing_file("trace_pipe");
+       trace_file = get_tracing_instance_file("trace_pipe");
        if (!trace_file) {
                pr_err("failed to open trace_pipe\n");
                return -1;
@@ -993,7 +1063,7 @@ static int cleanup_func_latency(struct perf_ftrace *ftrace)
        if (ftrace->target.use_bpf)
                return perf_ftrace__latency_cleanup_bpf(ftrace);
 
-       reset_tracing_files(ftrace);
+       exit_tracing_instance();
        return 0;
 }
 
@@ -1304,17 +1374,20 @@ static int __cmd_profile(struct perf_ftrace *ftrace)
                goto out;
        }
 
+       if (init_tracing_instance() < 0)
+               goto out;
+
        if (reset_tracing_files(ftrace) < 0) {
                pr_err("failed to reset ftrace\n");
-               goto out;
+               goto out_reset;
        }
 
        /* reset ftrace buffer */
        if (write_tracing_file("trace", "0") < 0)
-               goto out;
+               goto out_reset;
 
        if (set_tracing_options(ftrace) < 0)
-               return -1;
+               goto out_reset;
 
        if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
                pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
@@ -1323,7 +1396,7 @@ static int __cmd_profile(struct perf_ftrace *ftrace)
 
        setup_pager();
 
-       trace_file = get_tracing_file("trace_pipe");
+       trace_file = get_tracing_instance_file("trace_pipe");
        if (!trace_file) {
                pr_err("failed to open trace_pipe\n");
                goto out_reset;
@@ -1385,7 +1458,7 @@ out_free_line:
 out_close_fd:
        close(trace_fd);
 out_reset:
-       reset_tracing_files(ftrace);
+       exit_tracing_instance();
 out:
        return (done && !workload_exec_errno) ? 0 : -1;
 }