perf top: Allow filters on events

Allow filters to be added to perf top events. One use is to workaround
issues with:
```
$ perf top --uid="$(id -u)"
```
which tries to scan /proc find processes belonging to the uid and can
fail in such a pid terminates between the scan and the
perf_event_open reporting:
```
Error:
The sys_perf_event_open() syscall returned with 3 (No such process) for event (cycles:P).
/bin/dmesg | grep -i perf may provide additional information.
```
A similar filter:
```
$ perf top -e cycles:P --filter "uid == $(id -u)"
```
doesn't fail this way.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Changbin Du <changbin.du@huawei.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20240524205227.244375-4-irogers@google.com
This commit is contained in:
Ian Rogers 2024-05-24 13:52:27 -07:00 committed by Namhyung Kim
parent d92aa899fe
commit af75201634
2 changed files with 13 additions and 0 deletions

View File

@ -43,6 +43,10 @@ Default is to monitor all CPUS.
encoding with the layout of the event control registers as described encoding with the layout of the event control registers as described
by entries in /sys/bus/event_source/devices/cpu/format/*. by entries in /sys/bus/event_source/devices/cpu/format/*.
--filter=<filter>::
Event filter. This option should follow an event selector (-e). For
syntax see linkperf:perf-record[1].
-E <entries>:: -E <entries>::
--entries=<entries>:: --entries=<entries>::
Display this many functions. Display this many functions.

View File

@ -1055,6 +1055,13 @@ try_again:
} }
} }
if (evlist__apply_filters(evlist, &counter)) {
pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",
counter->filter ?: "BPF", evsel__name(counter), errno,
str_error_r(errno, msg, sizeof(msg)));
goto out_err;
}
if (evlist__mmap(evlist, opts->mmap_pages) < 0) { if (evlist__mmap(evlist, opts->mmap_pages) < 0) {
ui__error("Failed to mmap with %d (%s)\n", ui__error("Failed to mmap with %d (%s)\n",
errno, str_error_r(errno, msg, sizeof(msg))); errno, str_error_r(errno, msg, sizeof(msg)));
@ -1462,6 +1469,8 @@ int cmd_top(int argc, const char **argv)
OPT_CALLBACK('e', "event", &parse_events_option_args, "event", OPT_CALLBACK('e', "event", &parse_events_option_args, "event",
"event selector. use 'perf list' to list available events", "event selector. use 'perf list' to list available events",
parse_events_option), parse_events_option),
OPT_CALLBACK(0, "filter", &top.evlist, "filter",
"event filter", parse_filter),
OPT_U64('c', "count", &opts->user_interval, "event period to sample"), OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
OPT_STRING('p', "pid", &target->pid, "pid", OPT_STRING('p', "pid", &target->pid, "pid",
"profile events on existing process id"), "profile events on existing process id"),