diff options
Diffstat (limited to 'tools/perf/builtin-ftrace.c')
-rw-r--r-- | tools/perf/builtin-ftrace.c | 101 |
1 files changed, 87 insertions, 14 deletions
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c index 7caa18d5ffc3..bba36ebc2aa7 100644 --- a/tools/perf/builtin-ftrace.c +++ b/tools/perf/builtin-ftrace.c @@ -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; } |