mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
perf ftrace: Use process/session specific trace settings
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>
This commit is contained in:
parent
e48b92f9e1
commit
ba5f102eec
|
|
@ -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 @@ static int __cmd_profile(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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user