* [PATCH v4 2/2] perf evsel: Find process with busy PMUs for EBUSY
2025-06-03 18:15 [PATCH v4 1/2] perf: Reveal PMU type in fdinfo Chun-Tse Shao
@ 2025-06-03 18:15 ` Chun-Tse Shao
2025-06-25 3:06 ` [PATCH v4 1/2] perf: Reveal PMU type in fdinfo Ian Rogers
1 sibling, 0 replies; 4+ messages in thread
From: Chun-Tse Shao @ 2025-06-03 18:15 UTC (permalink / raw)
To: linux-kernel
Cc: Chun-Tse Shao, Ian Rogers, peterz, mingo, acme, namhyung,
mark.rutland, alexander.shishkin, jolsa, adrian.hunter, kan.liang,
james.clark, howardchu95, weilin.wang, linux-perf-users
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.
Reviewed-by: Ian Rogers <irogers@google.com>
Signed-off-by: Chun-Tse Shao <ctshao@google.com>
---
v4:
Removed the first patch in v3 since it is merged.
Retested to make sure the patch still work.
v3: lore.kernel.org/20241106003007.2112584-3-ctshao@google.com/
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 d55482f094bf..fa281ea15a25 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -3619,7 +3619,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;
@@ -3660,29 +3661,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);
@@ -3799,7 +3832,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.49.0.1204.g71687c7c1d-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v4 1/2] perf: Reveal PMU type in fdinfo
2025-06-03 18:15 [PATCH v4 1/2] perf: Reveal PMU type in fdinfo Chun-Tse Shao
2025-06-03 18:15 ` [PATCH v4 2/2] perf evsel: Find process with busy PMUs for EBUSY Chun-Tse Shao
@ 2025-06-25 3:06 ` Ian Rogers
2025-07-09 15:25 ` Ian Rogers
1 sibling, 1 reply; 4+ messages in thread
From: Ian Rogers @ 2025-06-25 3:06 UTC (permalink / raw)
To: peterz, mingo
Cc: linux-kernel, Chun-Tse Shao, acme, namhyung, mark.rutland,
alexander.shishkin, jolsa, adrian.hunter, kan.liang, james.clark,
howardchu95, weilin.wang, linux-perf-users
On Tue, Jun 3, 2025 at 11:16 AM Chun-Tse Shao <ctshao@google.com> wrote:
>
> It gives useful info on knowing which PMUs are reserved by this process.
> Also add config which would be useful.
> Testing cycles:
>
> $ ./perf stat -e cycles &
> $ cat /proc/`pidof perf`/fdinfo/3
> pos: 0
> flags: 02000002
> mnt_id: 16
> ino: 3081
> perf_event_attr.type: 0
> perf_event_attr.config: 0
>
> Testing L1-dcache-load-misses:
>
> $ ./perf stat -e L1-dcache-load-misses &
> $ cat /proc/`pidof perf`/fdinfo/3
> pos: 0
> flags: 02000002
> mnt_id: 16
> ino: 1072
> perf_event_attr.type: 3
> perf_event_attr.config: 65536
>
> Reviewed-by: Ian Rogers <irogers@google.com>
> Signed-off-by: Chun-Tse Shao <ctshao@google.com>
Ping.
Thanks,
Ian
> ---
> v4:
> Removed the first patch in v3 since it is merged.
> Retested to make sure the patch still work.
>
> v3: lore.kernel.org/20241106003007.2112584-2-ctshao@google.com
>
> kernel/events/core.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 95e703891b24..bad563692d63 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -56,6 +56,7 @@
> #include <linux/buildid.h>
> #include <linux/task_work.h>
> #include <linux/percpu-rwsem.h>
> +#include <linux/seq_file.h>
>
> #include "internal.h"
>
> @@ -7077,6 +7078,14 @@ static int perf_fasync(int fd, struct file *filp, int on)
> return 0;
> }
>
> +static void perf_show_fdinfo(struct seq_file *m, struct file *f)
> +{
> + struct perf_event *event = f->private_data;
> +
> + seq_printf(m, "perf_event_attr.type:\t%u\n", event->orig_type);
> + seq_printf(m, "perf_event_attr.config:\t%llu\n", (unsigned long long)event->attr.config);
> +}
> +
> static const struct file_operations perf_fops = {
> .release = perf_release,
> .read = perf_read,
> @@ -7085,6 +7094,7 @@ static const struct file_operations perf_fops = {
> .compat_ioctl = perf_compat_ioctl,
> .mmap = perf_mmap,
> .fasync = perf_fasync,
> + .show_fdinfo = perf_show_fdinfo,
> };
>
> /*
> --
> 2.49.0.1204.g71687c7c1d-goog
>
^ permalink raw reply [flat|nested] 4+ messages in thread