Commit 278538dd authored by Ian Rogers's avatar Ian Rogers Committed by Namhyung Kim
Browse files

perf bench evlist-open-close: Switch user option to use BPF filter



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: default avatarIan Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250604174545.2853620-9-irogers@google.com


Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent bf1976dd
Loading
Loading
Loading
Loading
+21 −15
Original line number Diff line number Diff line
@@ -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 @@ static char *bench__repeat_event_string(const char *evstr, int n)

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: