perf bench evlist-open-close: Switch user option to use BPF filter
authorIan Rogers <irogers@google.com>
Wed, 4 Jun 2025 17:45:42 +0000 (10:45 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Mon, 9 Jun 2025 18:18:18 +0000 (11:18 -0700)
Finding user processes by scanning /proc is inherently racy and
results in perf_event_open failures. Use a BPF filter to drop samples
where the uid doesn't match.

Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250604174545.2853620-9-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/bench/evlist-open-close.c

index 79cedcf94a399145eb05f5145254bbe08e0bdeec..bfaf50e4e51933a7167f3ea7cc599411e6b592f5 100644 (file)
@@ -57,7 +57,7 @@ static int evlist__count_evsel_fds(struct evlist *evlist)
        return cnt;
 }
 
-static struct evlist *bench__create_evlist(char *evstr)
+static struct evlist *bench__create_evlist(char *evstr, const char *uid_str)
 {
        struct parse_events_error err;
        struct evlist *evlist = evlist__new();
@@ -78,6 +78,18 @@ static struct evlist *bench__create_evlist(char *evstr)
                goto out_delete_evlist;
        }
        parse_events_error__exit(&err);
+       if (uid_str) {
+               uid_t uid = parse_uid(uid_str);
+
+               if (uid == UINT_MAX) {
+                       pr_err("Invalid User: %s", uid_str);
+                       ret = -EINVAL;
+                       goto out_delete_evlist;
+               }
+               ret = parse_uid_filter(evlist, uid);
+               if (ret)
+                       goto out_delete_evlist;
+       }
        ret = evlist__create_maps(evlist, &opts.target);
        if (ret < 0) {
                pr_err("Not enough memory to create thread/cpu maps\n");
@@ -117,10 +129,10 @@ static int bench__do_evlist_open_close(struct evlist *evlist)
        return 0;
 }
 
-static int bench_evlist_open_close__run(char *evstr)
+static int bench_evlist_open_close__run(char *evstr, const char *uid_str)
 {
        // used to print statistics only
-       struct evlist *evlist = bench__create_evlist(evstr);
+       struct evlist *evlist = bench__create_evlist(evstr, uid_str);
        double time_average, time_stddev;
        struct timeval start, end, diff;
        struct stats time_stats;
@@ -142,7 +154,7 @@ static int bench_evlist_open_close__run(char *evstr)
 
        for (i = 0; i < iterations; i++) {
                pr_debug("Started iteration %d\n", i);
-               evlist = bench__create_evlist(evstr);
+               evlist = bench__create_evlist(evstr, uid_str);
                if (!evlist)
                        return -ENOMEM;
 
@@ -206,6 +218,7 @@ out_error:
 
 int bench_evlist_open_close(int argc, const char **argv)
 {
+       const char *uid_str = NULL;
        const struct option options[] = {
                OPT_STRING('e', "event", &event_string, "event",
                           "event selector. use 'perf list' to list available events"),
@@ -221,7 +234,7 @@ int bench_evlist_open_close(int argc, const char **argv)
                           "record events on existing process id"),
                OPT_STRING('t', "tid", &opts.target.tid, "tid",
                           "record events on existing thread id"),
-               OPT_STRING('u', "uid", &opts.target.uid_str, "user", "user to profile"),
+               OPT_STRING('u', "uid", &uid_str, "user", "user to profile"),
                OPT_BOOLEAN(0, "per-thread", &opts.target.per_thread, "use per-thread mmaps"),
                OPT_END()
        };
@@ -245,15 +258,8 @@ int bench_evlist_open_close(int argc, const char **argv)
                goto out;
        }
 
-       err = target__parse_uid(&opts.target);
-       if (err) {
-               target__strerror(&opts.target, err, errbuf, sizeof(errbuf));
-               pr_err("%s", errbuf);
-               goto out;
-       }
-
-       /* Enable ignoring missing threads when -u/-p option is defined. */
-       opts.ignore_missing_thread = opts.target.uid != UINT_MAX || opts.target.pid;
+       /* Enable ignoring missing threads when -p option is defined. */
+       opts.ignore_missing_thread = opts.target.pid;
 
        evstr = bench__repeat_event_string(event_string, nr_events);
        if (!evstr) {
@@ -261,7 +267,7 @@ int bench_evlist_open_close(int argc, const char **argv)
                goto out;
        }
 
-       err = bench_evlist_open_close__run(evstr);
+       err = bench_evlist_open_close__run(evstr, uid_str);
 
        free(evstr);
 out: