[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20241106003007.2112584-3-ctshao@google.com>
Date: Wed, 6 Nov 2024 00:30:07 +0000
From: Chun-Tse Shao <ctshao@...gle.com>
To: linux-kernel@...r.kernel.org
Cc: Peter Zijlstra <peterz@...radead.org>, Ingo Molnar <mingo@...hat.com>,
Arnaldo Carvalho de Melo <acme@...nel.org>, Namhyung Kim <namhyung@...nel.org>,
Mark Rutland <mark.rutland@....com>,
Alexander Shishkin <alexander.shishkin@...ux.intel.com>, Jiri Olsa <jolsa@...nel.org>,
Ian Rogers <irogers@...gle.com>, Adrian Hunter <adrian.hunter@...el.com>,
Kan Liang <kan.liang@...ux.intel.com>, Ze Gao <zegao2021@...il.com>,
Chun-Tse Shao <ctshao@...gle.com>, Weilin Wang <weilin.wang@...el.com>,
linux-perf-users@...r.kernel.org
Subject: [PATCH v3 3/3] perf evsel: Find process with busy PMUs for EBUSY
It parses fdinfo with PMU type, comparing with the event which failed to
open, and report the processes causing EBUSY error.
Testing cycles and intel_pt//
$ ./perf stat -e cycles &
[1] 55569
$ ./perf stat -e intel_pt// &
[2] 55683
$ ./perf stat -e intel_pt//
Error:
The PMU intel_pt counters are busy and in use by another process.
Possible processes:
55683 ./perf stat -e intel_pt//
Only perf with intel_pt was reported.
Signed-off-by: Chun-Tse Shao <ctshao@...gle.com>
Change-Id: Ic51a36ea3b2fd245663d7db78f35496bb4199d73
---
tools/perf/util/evsel.c | 79 +++++++++++++++++++++++++++++------------
1 file changed, 57 insertions(+), 22 deletions(-)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d001ecfa26bf7..5400b795d9233 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -3286,7 +3286,8 @@ static bool find_process(const char *name)
return ret ? false : true;
}
-static int dump_perf_event_processes(char *msg, size_t size)
+static int dump_perf_event_processes(const struct perf_event_attr *failed_attr,
+ char *msg, size_t size)
{
DIR *proc_dir;
struct dirent *proc_entry;
@@ -3327,29 +3328,61 @@ static int dump_perf_event_processes(char *msg, size_t size)
continue;
/* Take care as readlink doesn't null terminate the string. */
if (!strncmp(buf, "anon_inode:[perf_event]", link_size)) {
- int cmdline_fd;
- ssize_t cmdline_size;
-
- scnprintf(buf, sizeof(buf), "%s/cmdline", proc_entry->d_name);
- cmdline_fd = openat(dirfd(proc_dir), buf, O_RDONLY);
- if (cmdline_fd == -1)
- continue;
- cmdline_size = read(cmdline_fd, buf, sizeof(buf) - 1);
- close(cmdline_fd);
- if (cmdline_size < 0)
+ int fdinfo_fd;
+ ssize_t fdinfo_size;
+ char *line;
+ u32 perf_event_type = UINT32_MAX;
+
+ /* Let's check the PMU type reserved by this process */
+ scnprintf(buf, sizeof(buf), "%s/fdinfo/%s",
+ proc_entry->d_name, fd_entry->d_name);
+ fdinfo_fd = openat(dirfd(proc_dir), buf, O_RDONLY);
+ fdinfo_size = read(fdinfo_fd, buf, sizeof(buf) - 1);
+ if (fdinfo_size < 0)
continue;
- buf[cmdline_size] = '\0';
- for (ssize_t i = 0; i < cmdline_size; i++) {
- if (buf[i] == '\0')
- buf[i] = ' ';
+ buf[fdinfo_size] = '\0';
+
+ line = strtok(buf, "\n");
+ while (line != NULL) {
+ if (sscanf(line,
+ "perf_event_attr.type:\t%u",
+ &perf_event_type) == 1)
+ break;
+ line = strtok(NULL, "\n");
}
- if (printed == 0)
- printed += scnprintf(msg, size, "Possible processes:\n");
-
- printed += scnprintf(msg + printed, size - printed,
- "%s %s\n", proc_entry->d_name, buf);
- break;
+ /* Report the process which reserves the conflicted PMU. */
+ /* If fdinfo does not contain PMU type, report it too. */
+ if (perf_event_type == failed_attr->type ||
+ perf_event_type == UINT32_MAX) {
+ int cmdline_fd;
+ ssize_t cmdline_size;
+
+ scnprintf(buf, sizeof(buf),
+ "%s/cmdline",
+ proc_entry->d_name);
+ cmdline_fd = openat(dirfd(proc_dir), buf, O_RDONLY);
+ if (cmdline_fd == -1)
+ continue;
+ cmdline_size = read(cmdline_fd, buf, sizeof(buf) - 1);
+ close(cmdline_fd);
+ if (cmdline_size < 0)
+ continue;
+ buf[cmdline_size] = '\0';
+ for (ssize_t i = 0; i < cmdline_size; i++) {
+ if (buf[i] == '\0')
+ buf[i] = ' ';
+ }
+
+ if (printed == 0)
+ printed += scnprintf(
+ msg, size,
+ "Possible processes:\n");
+
+ printed += scnprintf(msg + printed, size - printed,
+ "%s %s\n", proc_entry->d_name, buf);
+ break;
+ }
}
}
closedir(fd_dir);
@@ -3458,7 +3491,9 @@ int evsel__open_strerror(struct evsel *evsel, struct target *target,
msg, size,
"The PMU %s counters are busy and in use by another process.\n",
evsel->pmu ? evsel->pmu->name : "");
- return printed + dump_perf_event_processes(msg + printed, size - printed);
+ return printed + dump_perf_event_processes(&evsel->core.attr,
+ msg + printed,
+ size - printed);
break;
case EINVAL:
if (evsel->core.attr.sample_type & PERF_SAMPLE_CODE_PAGE_SIZE && perf_missing_features.code_page_size)
--
2.47.0.199.ga7371fff76-goog
Powered by blists - more mailing lists