From patchwork Wed Jul 3 22:30:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13722935 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CD6D0191F70; Wed, 3 Jul 2024 22:30:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045837; cv=none; b=E5ibfQsG6RpaPdg40CS5Suxp/rXfLeeercqBf0NdmcWpDvSuEtKZ0SQKzRnYhca62Fvl6zgLJWin3L7YHnuETl3Y084s4ew2f5SWem83n5/w6sIC7bmDTcdjg7nl7TbrgnoumS/A7d6b/pQX6msm/UQNXzrwfWKtMMvoUeIVS+A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045837; c=relaxed/simple; bh=nndiyJer93s+jzwVVuO+Yfa6ZgVjNDXW/14wUZXaLpA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s42K7udvYeugXJOLmpHLgJiJVeZvzcOTkBP366MKCdGo+RviuTe2mlqMYMSF4lhFuqQf2ZL7Pg0EiLha57/9WS5p6m5g6ITOPIC3PjXt7RvTXRDlJOVrOROk+yl7/h0f6MrEJFksvKbZiSAPk2md7z8DhA8g7AQaxO1vsjqoND0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BHJ2AoUz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BHJ2AoUz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D9C3BC4AF0F; Wed, 3 Jul 2024 22:30:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720045837; bh=nndiyJer93s+jzwVVuO+Yfa6ZgVjNDXW/14wUZXaLpA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BHJ2AoUz6xU6M27ml3hFeQBSb1QGJnSXZHFaRug1qfPlZ7o8/PnnjZObJasvp+fPj RC4mBZMCVK6TKWGdH0d7SlcshhfxxdL0Wm1nfXqpdVPcB3LioyPqjjPqNrodhln9l2 nM3eIuBos6hrysxnvvVvHZvAJsnQ9E7P+kAnnaFrvFY4/O0tOXHIXoRkBFlVv/piwJ AS2Go8I2T/IoRgJaBOMsXtAQF/HaCRA6mXCx2DLj84DG4VU8JBz/D7yafIC4aFZMg4 /1ffTvM7gzs7Tftwbk6i/tjNrP8c12xqNs9dvGt2OZCOq6mhYNG/gAkHh0vW+HctR2 EjyRIUyqdkU6g== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers , Kan Liang Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, KP Singh , Song Liu , bpf@vger.kernel.org, Stephane Eranian Subject: [PATCH v3 1/8] perf bpf-filter: Make filters map a single entry hashmap Date: Wed, 3 Jul 2024 15:30:28 -0700 Message-ID: <20240703223035.2024586-2-namhyung@kernel.org> X-Mailer: git-send-email 2.45.2.803.g4e1b14247a-goog In-Reply-To: <20240703223035.2024586-1-namhyung@kernel.org> References: <20240703223035.2024586-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 And the value is now an array. This is to support multiple filter entries in the map later. No functional changes intended. Signed-off-by: Namhyung Kim --- tools/perf/util/bpf-filter.c | 81 ++++++++++++++------ tools/perf/util/bpf_skel/sample-filter.h | 1 + tools/perf/util/bpf_skel/sample_filter.bpf.c | 39 +++++----- 3 files changed, 78 insertions(+), 43 deletions(-) diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c index 04f98b6bb291..2510832d83f9 100644 --- a/tools/perf/util/bpf-filter.c +++ b/tools/perf/util/bpf-filter.c @@ -93,71 +93,102 @@ static int check_sample_flags(struct evsel *evsel, struct perf_bpf_filter_expr * int perf_bpf_filter__prepare(struct evsel *evsel) { - int i, x, y, fd; + int i, x, y, fd, ret; struct sample_filter_bpf *skel; struct bpf_program *prog; struct bpf_link *link; struct perf_bpf_filter_expr *expr; + struct perf_bpf_filter_entry *entry; + + entry = calloc(MAX_FILTERS, sizeof(*entry)); + if (entry == NULL) + return -1; skel = sample_filter_bpf__open_and_load(); if (!skel) { pr_err("Failed to load perf sample-filter BPF skeleton\n"); - return -1; + ret = -EPERM; + goto err; } i = 0; fd = bpf_map__fd(skel->maps.filters); list_for_each_entry(expr, &evsel->bpf_filters, list) { - struct perf_bpf_filter_entry entry = { - .op = expr->op, - .part = expr->part, - .term = expr->term, - .value = expr->val, - }; + if (check_sample_flags(evsel, expr) < 0) { + ret = -EINVAL; + goto err; + } - if (check_sample_flags(evsel, expr) < 0) - return -1; + if (i == MAX_FILTERS) { + ret = -E2BIG; + goto err; + } - bpf_map_update_elem(fd, &i, &entry, BPF_ANY); + entry[i].op = expr->op; + entry[i].part = expr->part; + entry[i].term = expr->term; + entry[i].value = expr->val; i++; if (expr->op == PBF_OP_GROUP_BEGIN) { struct perf_bpf_filter_expr *group; list_for_each_entry(group, &expr->groups, list) { - struct perf_bpf_filter_entry group_entry = { - .op = group->op, - .part = group->part, - .term = group->term, - .value = group->val, - }; - bpf_map_update_elem(fd, &i, &group_entry, BPF_ANY); + if (i == MAX_FILTERS) { + ret = -E2BIG; + goto err; + } + + entry[i].op = group->op; + entry[i].part = group->part; + entry[i].term = group->term; + entry[i].value = group->val; i++; } - memset(&entry, 0, sizeof(entry)); - entry.op = PBF_OP_GROUP_END; - bpf_map_update_elem(fd, &i, &entry, BPF_ANY); + if (i == MAX_FILTERS) { + ret = -E2BIG; + goto err; + } + + entry[i].op = PBF_OP_GROUP_END; i++; } } - if (i > MAX_FILTERS) { - pr_err("Too many filters: %d (max = %d)\n", i, MAX_FILTERS); - return -1; + if (i < MAX_FILTERS) { + /* to terminate the loop early */ + entry[i].op = PBF_OP_DONE; + i++; + } + + /* The filters map has only one entry for now */ + i = 0; + if (bpf_map_update_elem(fd, &i, entry, BPF_ANY) < 0) { + ret = -errno; + pr_err("Failed to update the filter map\n"); + goto err; } + prog = skel->progs.perf_sample_filter; for (x = 0; x < xyarray__max_x(evsel->core.fd); x++) { for (y = 0; y < xyarray__max_y(evsel->core.fd); y++) { link = bpf_program__attach_perf_event(prog, FD(evsel, x, y)); if (IS_ERR(link)) { pr_err("Failed to attach perf sample-filter program\n"); - return PTR_ERR(link); + ret = PTR_ERR(link); + goto err; } } } + free(entry); evsel->bpf_skel = skel; return 0; + +err: + free(entry); + sample_filter_bpf__destroy(skel); + return ret; } int perf_bpf_filter__destroy(struct evsel *evsel) diff --git a/tools/perf/util/bpf_skel/sample-filter.h b/tools/perf/util/bpf_skel/sample-filter.h index 350efa121026..bb6a1b91f1df 100644 --- a/tools/perf/util/bpf_skel/sample-filter.h +++ b/tools/perf/util/bpf_skel/sample-filter.h @@ -14,6 +14,7 @@ enum perf_bpf_filter_op { PBF_OP_AND, PBF_OP_GROUP_BEGIN, PBF_OP_GROUP_END, + PBF_OP_DONE, }; enum perf_bpf_filter_term { diff --git a/tools/perf/util/bpf_skel/sample_filter.bpf.c b/tools/perf/util/bpf_skel/sample_filter.bpf.c index f59985101973..0d56e52b922c 100644 --- a/tools/perf/util/bpf_skel/sample_filter.bpf.c +++ b/tools/perf/util/bpf_skel/sample_filter.bpf.c @@ -9,10 +9,10 @@ /* BPF map that will be filled by user space */ struct filters { - __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(type, BPF_MAP_TYPE_HASH); __type(key, int); - __type(value, struct perf_bpf_filter_entry); - __uint(max_entries, MAX_FILTERS); + __type(value, struct perf_bpf_filter_entry[MAX_FILTERS]); + __uint(max_entries, 1); } filters SEC(".maps"); int dropped; @@ -179,39 +179,39 @@ int perf_sample_filter(void *ctx) __u64 sample_data; int in_group = 0; int group_result = 0; - int i; + int i, k; kctx = bpf_cast_to_kern_ctx(ctx); - for (i = 0; i < MAX_FILTERS; i++) { - int key = i; /* needed for verifier :( */ + k = 0; + entry = bpf_map_lookup_elem(&filters, &k); + if (entry == NULL) + goto drop; - entry = bpf_map_lookup_elem(&filters, &key); - if (entry == NULL) - break; - sample_data = perf_get_sample(kctx, entry); + for (i = 0; i < MAX_FILTERS; i++) { + sample_data = perf_get_sample(kctx, &entry[i]); - switch (entry->op) { + switch (entry[i].op) { case PBF_OP_EQ: - CHECK_RESULT(sample_data, ==, entry->value) + CHECK_RESULT(sample_data, ==, entry[i].value) break; case PBF_OP_NEQ: - CHECK_RESULT(sample_data, !=, entry->value) + CHECK_RESULT(sample_data, !=, entry[i].value) break; case PBF_OP_GT: - CHECK_RESULT(sample_data, >, entry->value) + CHECK_RESULT(sample_data, >, entry[i].value) break; case PBF_OP_GE: - CHECK_RESULT(sample_data, >=, entry->value) + CHECK_RESULT(sample_data, >=, entry[i].value) break; case PBF_OP_LT: - CHECK_RESULT(sample_data, <, entry->value) + CHECK_RESULT(sample_data, <, entry[i].value) break; case PBF_OP_LE: - CHECK_RESULT(sample_data, <=, entry->value) + CHECK_RESULT(sample_data, <=, entry[i].value) break; case PBF_OP_AND: - CHECK_RESULT(sample_data, &, entry->value) + CHECK_RESULT(sample_data, &, entry[i].value) break; case PBF_OP_GROUP_BEGIN: in_group = 1; @@ -222,6 +222,9 @@ int perf_sample_filter(void *ctx) goto drop; in_group = 0; break; + case PBF_OP_DONE: + /* no failures so far, accept it */ + return 1; } } /* generate sample data */ From patchwork Wed Jul 3 22:30:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13722936 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6456E194136; Wed, 3 Jul 2024 22:30:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045838; cv=none; b=mxpZaSJEj/fPK5ZrH1VWqTbWHYgyDkAz6CBNJ66QXat4fKnYSQYJTR/9soEqUkt3804AFH3WTeT73VkbiOo4SitfRLOUCGvFbMUxdZ7MbLd0TgIOpLpFrFGnpYD6yP4//EAeUZJsE2NmWwtVx51Ibhqcbt6fPMLcNvWRcpIKXs0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045838; c=relaxed/simple; bh=RMGaifxTM+7upI+r5g93pzdKZLIfNspeQTFX+Ryz3SE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QxHIwQ86d0K+FnB84Q/8DcEoLrkp82sULzMaMJ3yfWIVKl5pg1rS4WBk1ogqjMI7V5IwfDrqRbmVt0FcEk9RoZ2zFizwXygRjUOmYBk8ad4kCxWXYyP52j6dDDOSozSEl9zfrbmy+noCyXdV6F8YCWUq90IioeAwjUK6Vbh8bBs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UNCPv1Q4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UNCPv1Q4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 70FA9C4AF12; Wed, 3 Jul 2024 22:30:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720045837; bh=RMGaifxTM+7upI+r5g93pzdKZLIfNspeQTFX+Ryz3SE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UNCPv1Q4MNTnjfCkytaHXPTF1Uq7bcmtaiQ4/3zdPfOi0PmHOpVvPY7xf3UFPM+f9 IpdgNGrqWtrJIJuq0IFUbtGgR4OuwmBOQ1SuhVg7FAzAPK8A8m8yCK+1GNoBfx1zDY 6q1/RrXe1nELREErhfgLSgMiFiQCX31FC9x/PEwqBUh2Q3ehUnt5wyiAC/t88fSLuf Wpd1HL0T2H3S8hFYrXIN0mNfvQ1T1qloEMDGqCBqpfCAcZxlX5XMdRkA529oX2R4kJ BBpY6ZhZcps+NdPWL85FkTDW1X8WCUM5RvDJg5CTBx2N20vx/FEfYYAGi4czndeMis F0DSM0inPz1OA== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers , Kan Liang Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, KP Singh , Song Liu , bpf@vger.kernel.org, Stephane Eranian Subject: [PATCH v3 2/8] perf bpf-filter: Pass 'target' to perf_bpf_filter__prepare() Date: Wed, 3 Jul 2024 15:30:29 -0700 Message-ID: <20240703223035.2024586-3-namhyung@kernel.org> X-Mailer: git-send-email 2.45.2.803.g4e1b14247a-goog In-Reply-To: <20240703223035.2024586-1-namhyung@kernel.org> References: <20240703223035.2024586-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This is needed to prepare target-specific actions in the later patch. We want to reuse the pinned BPF program and map for regular users to profile their own processes. Signed-off-by: Namhyung Kim --- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/util/bpf-filter.c | 2 +- tools/perf/util/bpf-filter.h | 6 ++++-- tools/perf/util/evlist.c | 5 +++-- tools/perf/util/evlist.h | 4 +++- 8 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 019305b94e5f..e855a7688008 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -1389,7 +1389,7 @@ static int record__open(struct record *rec) "even with a suitable vmlinux or kallsyms file.\n\n"); } - if (evlist__apply_filters(evlist, &pos)) { + if (evlist__apply_filters(evlist, &pos, &opts->target)) { pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", pos->filter ?: "BPF", evsel__name(pos), errno, str_error_r(errno, msg, sizeof(msg))); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 661832756a24..1f92445f7480 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -833,7 +833,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) return -1; } - if (evlist__apply_filters(evsel_list, &counter)) { + if (evlist__apply_filters(evsel_list, &counter, &target)) { pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", counter->filter, evsel__name(counter), errno, str_error_r(errno, msg, sizeof(msg))); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index e8cbbf10d361..d1a06a88d693 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1055,7 +1055,7 @@ static int perf_top__start_counters(struct perf_top *top) } } - if (evlist__apply_filters(evlist, &counter)) { + if (evlist__apply_filters(evlist, &counter, &opts->target)) { 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))); diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c42bc608954e..0f93ba83717d 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -3959,7 +3959,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) err = trace__expand_filters(trace, &evsel); if (err) goto out_delete_evlist; - err = evlist__apply_filters(evlist, &evsel); + err = evlist__apply_filters(evlist, &evsel, &trace->opts.target); if (err < 0) goto out_error_apply_filters; diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c index 2510832d83f9..0b2eca56aa10 100644 --- a/tools/perf/util/bpf-filter.c +++ b/tools/perf/util/bpf-filter.c @@ -91,7 +91,7 @@ static int check_sample_flags(struct evsel *evsel, struct perf_bpf_filter_expr * return -1; } -int perf_bpf_filter__prepare(struct evsel *evsel) +int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target __maybe_unused) { int i, x, y, fd, ret; struct sample_filter_bpf *skel; diff --git a/tools/perf/util/bpf-filter.h b/tools/perf/util/bpf-filter.h index cd6764442c16..605a3d0226e0 100644 --- a/tools/perf/util/bpf-filter.h +++ b/tools/perf/util/bpf-filter.h @@ -16,6 +16,7 @@ struct perf_bpf_filter_expr { }; struct evsel; +struct target; #ifdef HAVE_BPF_SKEL struct perf_bpf_filter_expr *perf_bpf_filter_expr__new(enum perf_bpf_filter_term term, @@ -23,7 +24,7 @@ struct perf_bpf_filter_expr *perf_bpf_filter_expr__new(enum perf_bpf_filter_term enum perf_bpf_filter_op op, unsigned long val); int perf_bpf_filter__parse(struct list_head *expr_head, const char *str); -int perf_bpf_filter__prepare(struct evsel *evsel); +int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target); int perf_bpf_filter__destroy(struct evsel *evsel); u64 perf_bpf_filter__lost_count(struct evsel *evsel); @@ -34,7 +35,8 @@ static inline int perf_bpf_filter__parse(struct list_head *expr_head __maybe_unu { return -EOPNOTSUPP; } -static inline int perf_bpf_filter__prepare(struct evsel *evsel __maybe_unused) +static inline int perf_bpf_filter__prepare(struct evsel *evsel __maybe_unused, + struct target *target __maybe_unused) { return -EOPNOTSUPP; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3a719edafc7a..1417f9a23083 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1086,7 +1086,8 @@ int evlist__create_maps(struct evlist *evlist, struct target *target) return -1; } -int evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel) +int evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel, + struct target *target) { struct evsel *evsel; int err = 0; @@ -1108,7 +1109,7 @@ int evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel) * non-tracepoint events can have BPF filters. */ if (!list_empty(&evsel->bpf_filters)) { - err = perf_bpf_filter__prepare(evsel); + err = perf_bpf_filter__prepare(evsel, target); if (err) { *err_evsel = evsel; break; diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index cb91dc9117a2..cccc34da5a02 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -20,6 +20,7 @@ struct pollfd; struct thread_map; struct perf_cpu_map; struct record_opts; +struct target; /* * State machine of bkw_mmap_state: @@ -212,7 +213,8 @@ void evlist__enable_non_dummy(struct evlist *evlist); void evlist__set_selected(struct evlist *evlist, struct evsel *evsel); int evlist__create_maps(struct evlist *evlist, struct target *target); -int evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel); +int evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel, + struct target *target); u64 __evlist__combined_sample_type(struct evlist *evlist); u64 evlist__combined_sample_type(struct evlist *evlist); From patchwork Wed Jul 3 22:30:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13722937 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC2011946C7; Wed, 3 Jul 2024 22:30:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045838; cv=none; b=GSsJVDTQtEhVK6m6f5vta1c/kvb7fG+rgyYv1HKfm/o4R7qyNTCo+a5wePgYMF5djGvihqiZxJpXW+tLcv+QEBv2Ax2KXVm118FIRRMxNNnNdIssBI+QtNs9TjyVdlY6SipaYugl0DhJxQtj+NhW9El6x8I6RLqL5BqTbWIPYaY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045838; c=relaxed/simple; bh=rbfHsY9w9hApFB/nzPkZ1WXn/UvGNLB9ZwR3TO7Io1Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CCAxEVEhzHEbg+uBBjbsdBBQw0n155MlOOMKyIvIV2+FqNdKah3VluFzq+TtSEJgf0l4vzc8DEeMdER1hvRzHovvmmh+CMmP/Nf3oWBvO9G3iXtYkvKkqnuY41zioaiJYcS2tJiFRhbJ8mVbHcsKSqhYYfWbdm5N+c+gplLXzQA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UFusgQcZ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UFusgQcZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0A32FC4AF0F; Wed, 3 Jul 2024 22:30:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720045838; bh=rbfHsY9w9hApFB/nzPkZ1WXn/UvGNLB9ZwR3TO7Io1Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UFusgQcZ8Y1CKmW8MYconhT6c8VGS81/ysOZ3F0UKzNlUb8W3qwjdAR+Rhm7E1Sph QbLUaU8la6ffE0cs2qiQ85JyYXirLR8iFKMyLaNfeqQruwpCa80zOMX0Fm+SxRzx9y SihFFOlZoLfP+vuODH3nzrxFArr4pV3DpSQJFhLq1L1PQ/EhjgLuCdhfOkaBK6D8Tj ZhuC/egpigeYeHWbJxEG8BXa6GbdeIUpLQfhmlxK6xRA1EbgkXkolgar+E/Mae6V9N Ubb/kq7SzGJcY9GG7vNcWvV2HCxyU3oL127K8uZfJm2Gm4ng024nx5m0Xa73/rkxqQ zz6UGms5OO70g== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers , Kan Liang Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, KP Singh , Song Liu , bpf@vger.kernel.org, Stephane Eranian Subject: [PATCH v3 3/8] perf bpf-filter: Split per-task filter use case Date: Wed, 3 Jul 2024 15:30:30 -0700 Message-ID: <20240703223035.2024586-4-namhyung@kernel.org> X-Mailer: git-send-email 2.45.2.803.g4e1b14247a-goog In-Reply-To: <20240703223035.2024586-1-namhyung@kernel.org> References: <20240703223035.2024586-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 If the target is a list of tasks, it can use a shared hash map for filter expressions. The key of the filter map is an integer index like in an array. A separate pid_hash map is added to get the index for the filter map using the tgid. For system-wide mode including per-cpu or per-user targets are handled by the single entry map like before. Signed-off-by: Namhyung Kim --- tools/perf/util/bpf-filter.c | 186 +++++++++++++++---- tools/perf/util/bpf_skel/sample-filter.h | 1 + tools/perf/util/bpf_skel/sample_filter.bpf.c | 21 +++ 3 files changed, 168 insertions(+), 40 deletions(-) diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c index 0b2eca56aa10..5ec0e0955ec4 100644 --- a/tools/perf/util/bpf-filter.c +++ b/tools/perf/util/bpf-filter.c @@ -3,10 +3,13 @@ #include #include +#include #include +#include #include "util/debug.h" #include "util/evsel.h" +#include "util/target.h" #include "util/bpf-filter.h" #include @@ -91,38 +94,17 @@ static int check_sample_flags(struct evsel *evsel, struct perf_bpf_filter_expr * return -1; } -int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target __maybe_unused) +static int get_filter_entries(struct evsel *evsel, struct perf_bpf_filter_entry *entry) { - int i, x, y, fd, ret; - struct sample_filter_bpf *skel; - struct bpf_program *prog; - struct bpf_link *link; + int i = 0; struct perf_bpf_filter_expr *expr; - struct perf_bpf_filter_entry *entry; - - entry = calloc(MAX_FILTERS, sizeof(*entry)); - if (entry == NULL) - return -1; - - skel = sample_filter_bpf__open_and_load(); - if (!skel) { - pr_err("Failed to load perf sample-filter BPF skeleton\n"); - ret = -EPERM; - goto err; - } - i = 0; - fd = bpf_map__fd(skel->maps.filters); list_for_each_entry(expr, &evsel->bpf_filters, list) { - if (check_sample_flags(evsel, expr) < 0) { - ret = -EINVAL; - goto err; - } + if (check_sample_flags(evsel, expr) < 0) + return -EINVAL; - if (i == MAX_FILTERS) { - ret = -E2BIG; - goto err; - } + if (i == MAX_FILTERS) + return -E2BIG; entry[i].op = expr->op; entry[i].part = expr->part; @@ -134,10 +116,8 @@ int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target __maybe_ struct perf_bpf_filter_expr *group; list_for_each_entry(group, &expr->groups, list) { - if (i == MAX_FILTERS) { - ret = -E2BIG; - goto err; - } + if (i == MAX_FILTERS) + return -E2BIG; entry[i].op = group->op; entry[i].part = group->part; @@ -146,10 +126,8 @@ int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target __maybe_ i++; } - if (i == MAX_FILTERS) { - ret = -E2BIG; - goto err; - } + if (i == MAX_FILTERS) + return -E2BIG; entry[i].op = PBF_OP_GROUP_END; i++; @@ -161,15 +139,143 @@ int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target __maybe_ entry[i].op = PBF_OP_DONE; i++; } + return 0; +} + +static int convert_to_tgid(int tid) +{ + char path[128]; + char *buf, *p, *q; + int tgid; + size_t len; + + scnprintf(path, sizeof(path), "%d/status", tid); + if (procfs__read_str(path, &buf, &len) < 0) + return -1; - /* The filters map has only one entry for now */ - i = 0; - if (bpf_map_update_elem(fd, &i, entry, BPF_ANY) < 0) { - ret = -errno; - pr_err("Failed to update the filter map\n"); + p = strstr(buf, "Tgid:"); + if (p == NULL) { + free(buf); + return -1; + } + + tgid = strtol(p + 6, &q, 0); + free(buf); + if (*q != '\n') + return -1; + + return tgid; +} + +static int update_pid_hash(struct sample_filter_bpf *skel, struct evsel *evsel, + struct perf_bpf_filter_entry *entry) +{ + int filter_idx; + int nr, last; + int fd = bpf_map__fd(skel->maps.filters); + struct perf_thread_map *threads; + + /* Find the first available entry in the filters map */ + for (filter_idx = 0; filter_idx < MAX_FILTERS; filter_idx++) { + if (bpf_map_update_elem(fd, &filter_idx, entry, BPF_NOEXIST) == 0) + break; + } + + if (filter_idx == MAX_FILTERS) { + pr_err("Too many users for the filter map\n"); + return -EBUSY; + } + + threads = perf_evsel__threads(&evsel->core); + if (threads == NULL) { + pr_err("Cannot get the thread list of the event\n"); + return -EINVAL; + } + + /* save the index to a hash map */ + fd = bpf_map__fd(skel->maps.pid_hash); + + last = -1; + nr = perf_thread_map__nr(threads); + for (int i = 0; i < nr; i++) { + int pid = perf_thread_map__pid(threads, i); + int tgid; + + /* it actually needs tgid, let's get tgid from /proc. */ + tgid = convert_to_tgid(pid); + if (tgid < 0) { + /* the thread may be dead, ignore. */ + continue; + } + + if (tgid == last) + continue; + last = tgid; + + if (bpf_map_update_elem(fd, &tgid, &filter_idx, BPF_ANY) < 0) { + pr_err("Failed to update the pid hash\n"); + return -errno; + } + pr_debug("pid hash: %d -> %d\n", tgid, filter_idx); + } + return 0; +} + +int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target) +{ + int i, x, y, fd, ret; + struct sample_filter_bpf *skel = NULL; + struct bpf_program *prog; + struct bpf_link *link; + struct perf_bpf_filter_entry *entry; + bool needs_pid_hash = !target__has_cpu(target) && !target->uid_str; + + entry = calloc(MAX_FILTERS, sizeof(*entry)); + if (entry == NULL) + return -1; + + ret = get_filter_entries(evsel, entry); + if (ret < 0) { + pr_err("Failed to process filter entries\n"); + goto err; + } + + skel = sample_filter_bpf__open(); + if (!skel) { + pr_err("Failed to open perf sample-filter BPF skeleton\n"); + ret = -EPERM; goto err; } + if (needs_pid_hash) { + bpf_map__set_max_entries(skel->maps.filters, MAX_FILTERS); + bpf_map__set_max_entries(skel->maps.pid_hash, MAX_PIDS); + skel->rodata->use_pid_hash = 1; + } + + if (sample_filter_bpf__load(skel) < 0) { + pr_err("Failed to load perf sample-filter BPF skeleton\n"); + ret = -EPERM; + goto err; + } + + if (needs_pid_hash) { + /* The filters map is shared among other processes */ + ret = update_pid_hash(skel, evsel, entry); + if (ret < 0) + goto err; + } else { + i = 0; + fd = bpf_map__fd(skel->maps.filters); + + /* The filters map has only one entry in this case */ + if (bpf_map_update_elem(fd, &i, entry, BPF_ANY) < 0) { + ret = -errno; + pr_err("Failed to update the filter map\n"); + goto err; + } + } + prog = skel->progs.perf_sample_filter; for (x = 0; x < xyarray__max_x(evsel->core.fd); x++) { for (y = 0; y < xyarray__max_y(evsel->core.fd); y++) { diff --git a/tools/perf/util/bpf_skel/sample-filter.h b/tools/perf/util/bpf_skel/sample-filter.h index bb6a1b91f1df..e666bfd5fbdd 100644 --- a/tools/perf/util/bpf_skel/sample-filter.h +++ b/tools/perf/util/bpf_skel/sample-filter.h @@ -2,6 +2,7 @@ #define PERF_UTIL_BPF_SKEL_SAMPLE_FILTER_H #define MAX_FILTERS 64 +#define MAX_PIDS (16 * 1024) /* supported filter operations */ enum perf_bpf_filter_op { diff --git a/tools/perf/util/bpf_skel/sample_filter.bpf.c b/tools/perf/util/bpf_skel/sample_filter.bpf.c index 0d56e52b922c..c5273f06fa45 100644 --- a/tools/perf/util/bpf_skel/sample_filter.bpf.c +++ b/tools/perf/util/bpf_skel/sample_filter.bpf.c @@ -15,7 +15,16 @@ struct filters { __uint(max_entries, 1); } filters SEC(".maps"); +/* tgid to filter index */ +struct pid_hash { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, int); + __type(value, int); + __uint(max_entries, 1); +} pid_hash SEC(".maps"); + int dropped; +volatile const int use_pid_hash; void *bpf_cast_to_kern_ctx(void *) __ksym; @@ -184,6 +193,18 @@ int perf_sample_filter(void *ctx) kctx = bpf_cast_to_kern_ctx(ctx); k = 0; + + if (use_pid_hash) { + int tgid = bpf_get_current_pid_tgid() >> 32; + int *idx; + + idx = bpf_map_lookup_elem(&pid_hash, &tgid); + if (idx) + k = *idx; + else + goto drop; + } + entry = bpf_map_lookup_elem(&filters, &k); if (entry == NULL) goto drop; From patchwork Wed Jul 3 22:30:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13722938 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F636194A73; Wed, 3 Jul 2024 22:30:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045839; cv=none; b=RPWcHNLni55a1FaHPISehmAFGPSuN5E2+8Fy+pZwNinwH8z07fSOqoHHbvDb3EmOSCnN/DC75pgEWM3vfgAq/pH9WSSUDFq2vqSgMgK4vCRDLJb89YqT65pIPzac77VQx3Sb/DyD887x+iRdRwNQS85ccDr3+KD0/Gj/rB2m468= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045839; c=relaxed/simple; bh=a/vQ9nQc8NEhneTRitImTcXL8xixYG3rfate3UALpBw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uPo+n/7cOgyfMcPX0OhRGckEsKvshTD8UjmfYBsWxITvEcycC3RmlbmAIky6k2Gg3x1j6Yi/8LT4DF8x4bajRCg8l9ftIrNLDy84Afhg4WG0+HNhcc/VF2b5awbSjz36K4tfSSW8QFCXUI3HtQEwtRIpHhUK/9c6qKaHcl1lJ5c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=elHEBRlg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="elHEBRlg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9322BC4AF12; Wed, 3 Jul 2024 22:30:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720045839; bh=a/vQ9nQc8NEhneTRitImTcXL8xixYG3rfate3UALpBw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=elHEBRlgHhMaDfqpafJ+4Z/KZvJ+OfPyNEOpRpO+ztVlZnDpIXr5qrmBXPtIur/nD P5G9t8wlpjYgI2tuO3lVVx6icZ9HkHeoQOpCPVXMsDzmHi3iQvxWXeT5dzpWCr+sQ3 LRshx2PDdOpSroJDrdAKhz3Bx8mXi44L6PWPDs/VptIAQ0ryDbS+Kbz4lcz3VEukmt 9OS3Nb0Q6A6mzKjVlrMPrO4KGdpWPO/OeQzDRFABLz/QOnHeuFZU41/jY8q4qG24pX M40+PqbnW4qYPBRV5TUE1wqxVZ/Vd0/2x6zFpGlwOk/dp4ZCy6huiu7Vp8ncFtCyZJ exM70MtvXl4fA== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers , Kan Liang Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, KP Singh , Song Liu , bpf@vger.kernel.org, Stephane Eranian Subject: [PATCH v3 4/8] perf bpf-filter: Support pin/unpin BPF object Date: Wed, 3 Jul 2024 15:30:31 -0700 Message-ID: <20240703223035.2024586-5-namhyung@kernel.org> X-Mailer: git-send-email 2.45.2.803.g4e1b14247a-goog In-Reply-To: <20240703223035.2024586-1-namhyung@kernel.org> References: <20240703223035.2024586-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 And use the pinned objects for unprivileged users to profile their own tasks. The BPF objects need to be pinned in the BPF-fs by root first and it'll be handled in the later patch. Signed-off-by: Namhyung Kim --- tools/perf/util/bpf-filter.c | 230 +++++++++++++++++++++++++++++------ tools/perf/util/bpf-filter.h | 13 ++ 2 files changed, 209 insertions(+), 34 deletions(-) diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c index 5ec0e0955ec4..37ed6c48debf 100644 --- a/tools/perf/util/bpf-filter.c +++ b/tools/perf/util/bpf-filter.c @@ -1,5 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ #include +#include +#include +#include #include #include @@ -23,6 +26,9 @@ #define __PERF_SAMPLE_TYPE(tt, st, opt) { tt, #st, opt } #define PERF_SAMPLE_TYPE(_st, opt) __PERF_SAMPLE_TYPE(PBF_TERM_##_st, PERF_SAMPLE_##_st, opt) +/* Index in the pinned 'filters' map. Should be released after use. */ +static int pinned_filter_idx = -1; + static const struct perf_sample_info { enum perf_bpf_filter_term type; const char *name; @@ -47,6 +53,8 @@ static const struct perf_sample_info { PERF_SAMPLE_TYPE(DATA_PAGE_SIZE, "--data-page-size"), }; +static int get_pinned_fd(const char *name); + static const struct perf_sample_info *get_sample_info(enum perf_bpf_filter_term type) { size_t i; @@ -167,19 +175,26 @@ static int convert_to_tgid(int tid) return tgid; } -static int update_pid_hash(struct sample_filter_bpf *skel, struct evsel *evsel, - struct perf_bpf_filter_entry *entry) +static int update_pid_hash(struct evsel *evsel, struct perf_bpf_filter_entry *entry) { int filter_idx; - int nr, last; - int fd = bpf_map__fd(skel->maps.filters); + int fd, nr, last; struct perf_thread_map *threads; + fd = get_pinned_fd("filters"); + if (fd < 0) { + pr_debug("cannot get fd for 'filters' map\n"); + return fd; + } + /* Find the first available entry in the filters map */ for (filter_idx = 0; filter_idx < MAX_FILTERS; filter_idx++) { - if (bpf_map_update_elem(fd, &filter_idx, entry, BPF_NOEXIST) == 0) + if (bpf_map_update_elem(fd, &filter_idx, entry, BPF_NOEXIST) == 0) { + pinned_filter_idx = filter_idx; break; + } } + close(fd); if (filter_idx == MAX_FILTERS) { pr_err("Too many users for the filter map\n"); @@ -193,7 +208,9 @@ static int update_pid_hash(struct sample_filter_bpf *skel, struct evsel *evsel, } /* save the index to a hash map */ - fd = bpf_map__fd(skel->maps.pid_hash); + fd = get_pinned_fd("pid_hash"); + if (fd < 0) + return fd; last = -1; nr = perf_thread_map__nr(threads); @@ -214,10 +231,12 @@ static int update_pid_hash(struct sample_filter_bpf *skel, struct evsel *evsel, if (bpf_map_update_elem(fd, &tgid, &filter_idx, BPF_ANY) < 0) { pr_err("Failed to update the pid hash\n"); - return -errno; + close(fd); + return -1; } pr_debug("pid hash: %d -> %d\n", tgid, filter_idx); } + close(fd); return 0; } @@ -240,40 +259,48 @@ int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target) goto err; } - skel = sample_filter_bpf__open(); - if (!skel) { - pr_err("Failed to open perf sample-filter BPF skeleton\n"); - ret = -EPERM; - goto err; - } + if (needs_pid_hash && geteuid() != 0) { + /* The filters map is shared among other processes */ + ret = update_pid_hash(evsel, entry); + if (ret < 0) + goto err; - if (needs_pid_hash) { - bpf_map__set_max_entries(skel->maps.filters, MAX_FILTERS); - bpf_map__set_max_entries(skel->maps.pid_hash, MAX_PIDS); - skel->rodata->use_pid_hash = 1; + fd = get_pinned_fd("perf_sample_filter"); + if (fd < 0) { + ret = fd; + goto err; + } + + for (x = 0; x < xyarray__max_x(evsel->core.fd); x++) { + for (y = 0; y < xyarray__max_y(evsel->core.fd); y++) { + ret = ioctl(FD(evsel, x, y), PERF_EVENT_IOC_SET_BPF, fd); + if (ret < 0) { + pr_err("Failed to attach perf sample-filter\n"); + goto err; + } + } + } + + close(fd); + free(entry); + return 0; } - if (sample_filter_bpf__load(skel) < 0) { + skel = sample_filter_bpf__open_and_load(); + if (!skel) { + ret = -errno; pr_err("Failed to load perf sample-filter BPF skeleton\n"); - ret = -EPERM; goto err; } - if (needs_pid_hash) { - /* The filters map is shared among other processes */ - ret = update_pid_hash(skel, evsel, entry); - if (ret < 0) - goto err; - } else { - i = 0; - fd = bpf_map__fd(skel->maps.filters); - - /* The filters map has only one entry in this case */ - if (bpf_map_update_elem(fd, &i, entry, BPF_ANY) < 0) { - ret = -errno; - pr_err("Failed to update the filter map\n"); - goto err; - } + i = 0; + fd = bpf_map__fd(skel->maps.filters); + + /* The filters map has only one entry in this case */ + if (bpf_map_update_elem(fd, &i, entry, BPF_ANY) < 0) { + ret = -errno; + pr_err("Failed to update the filter map\n"); + goto err; } prog = skel->progs.perf_sample_filter; @@ -306,6 +333,15 @@ int perf_bpf_filter__destroy(struct evsel *evsel) free(expr); } sample_filter_bpf__destroy(evsel->bpf_skel); + + if (pinned_filter_idx >= 0) { + int fd = get_pinned_fd("filters"); + + bpf_map_delete_elem(fd, &pinned_filter_idx); + pinned_filter_idx = -1; + close(fd); + } + return 0; } @@ -349,3 +385,129 @@ int perf_bpf_filter__parse(struct list_head *expr_head, const char *str) return ret; } + +int perf_bpf_filter__pin(void) +{ + struct sample_filter_bpf *skel; + char *path = NULL; + int dir_fd, ret = -1; + + skel = sample_filter_bpf__open(); + if (!skel) { + ret = -errno; + pr_err("Failed to open perf sample-filter BPF skeleton\n"); + goto err; + } + + /* pinned program will use pid-hash */ + bpf_map__set_max_entries(skel->maps.filters, MAX_FILTERS); + bpf_map__set_max_entries(skel->maps.pid_hash, MAX_PIDS); + skel->rodata->use_pid_hash = 1; + + if (sample_filter_bpf__load(skel) < 0) { + ret = -errno; + pr_err("Failed to load perf sample-filter BPF skeleton\n"); + goto err; + } + + if (asprintf(&path, "%s/fs/bpf/%s", sysfs__mountpoint(), + PERF_BPF_FILTER_PIN_PATH) < 0) { + ret = -errno; + pr_err("Failed to allocate pathname in the BPF-fs\n"); + goto err; + } + + ret = bpf_object__pin(skel->obj, path); + if (ret < 0) { + pr_err("Failed to pin BPF filter objects\n"); + goto err; + } + + /* setup access permissions for the pinned objects */ + dir_fd = open(path, O_PATH); + if (dir_fd < 0) { + bpf_object__unpin(skel->obj, path); + ret = dir_fd; + goto err; + } + + /* BPF-fs root has the sticky bit */ + if (fchmodat(dir_fd, "..", 01755, 0) < 0) { + pr_debug("chmod for BPF-fs failed\n"); + ret = -errno; + goto err_close; + } + + /* perf_filter directory */ + if (fchmodat(dir_fd, ".", 0755, 0) < 0) { + pr_debug("chmod for perf_filter directory failed?\n"); + ret = -errno; + goto err_close; + } + + /* programs need write permission for some reason */ + if (fchmodat(dir_fd, "perf_sample_filter", 0777, 0) < 0) { + pr_debug("chmod for perf_sample_filter failed\n"); + ret = -errno; + } + /* maps */ + if (fchmodat(dir_fd, "filters", 0666, 0) < 0) { + pr_debug("chmod for filters failed\n"); + ret = -errno; + } + if (fchmodat(dir_fd, "pid_hash", 0666, 0) < 0) { + pr_debug("chmod for pid_hash failed\n"); + ret = -errno; + } + +err_close: + close(dir_fd); + +err: + free(path); + sample_filter_bpf__destroy(skel); + return ret; +} + +int perf_bpf_filter__unpin(void) +{ + struct sample_filter_bpf *skel; + char *path = NULL; + int ret = -1; + + skel = sample_filter_bpf__open_and_load(); + if (!skel) { + ret = -errno; + pr_err("Failed to open perf sample-filter BPF skeleton\n"); + goto err; + } + + if (asprintf(&path, "%s/fs/bpf/%s", sysfs__mountpoint(), + PERF_BPF_FILTER_PIN_PATH) < 0) { + ret = -errno; + pr_err("Failed to allocate pathname in the BPF-fs\n"); + goto err; + } + + ret = bpf_object__unpin(skel->obj, path); + +err: + free(path); + sample_filter_bpf__destroy(skel); + return ret; +} + +static int get_pinned_fd(const char *name) +{ + char *path = NULL; + int fd; + + if (asprintf(&path, "%s/fs/bpf/%s/%s", sysfs__mountpoint(), + PERF_BPF_FILTER_PIN_PATH, name) < 0) + return -1; + + fd = bpf_obj_get(path); + + free(path); + return fd; +} diff --git a/tools/perf/util/bpf-filter.h b/tools/perf/util/bpf-filter.h index 605a3d0226e0..916ed7770b73 100644 --- a/tools/perf/util/bpf-filter.h +++ b/tools/perf/util/bpf-filter.h @@ -18,6 +18,9 @@ struct perf_bpf_filter_expr { struct evsel; struct target; +/* path in BPF-fs for the pinned program and maps */ +#define PERF_BPF_FILTER_PIN_PATH "perf_filter" + #ifdef HAVE_BPF_SKEL struct perf_bpf_filter_expr *perf_bpf_filter_expr__new(enum perf_bpf_filter_term term, int part, @@ -27,6 +30,8 @@ int perf_bpf_filter__parse(struct list_head *expr_head, const char *str); int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target); int perf_bpf_filter__destroy(struct evsel *evsel); u64 perf_bpf_filter__lost_count(struct evsel *evsel); +int perf_bpf_filter__pin(void); +int perf_bpf_filter__unpin(void); #else /* !HAVE_BPF_SKEL */ @@ -48,5 +53,13 @@ static inline u64 perf_bpf_filter__lost_count(struct evsel *evsel __maybe_unused { return 0; } +static inline int perf_bpf_filter__pin(void) +{ + return -EOPNOTSUPP; +} +static inline int perf_bpf_filter__unpin(void) +{ + return -EOPNOTSUPP; +} #endif /* HAVE_BPF_SKEL*/ #endif /* PERF_UTIL_BPF_FILTER_H */ From patchwork Wed Jul 3 22:30:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13722939 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B75F4194AD7; Wed, 3 Jul 2024 22:30:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045839; cv=none; b=PMX+PqpP1Qyq/JJYXz8eD13zm9yk78sHCq7NBbtm3PuGeFrJepwED3RdQsHSdpBw+SdTQRKii8l+LgduTv1GTC9tL0M9VJnaAGPY1ccQwIQrSV26CJdH8VQmlHTm0vvF3yDcDS8lyoXJBpew7gnD7EGvYilJ7LD/eKBeKC9tJrA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045839; c=relaxed/simple; bh=acxnBH33pEM3geRn+RlT87+ixutZtG8P8+um1GieHao=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nMyNyCid6quNkNWOLP2pH4UIDTvzFHV82tbvKg4QLaZBHPgd7b2u/+A/Eq8+fgkVyUP6mtbW5MD+HnXQnzm4W0yHwQB3BWCUW6+hHSDwK4z9hRvPAdecD78PcW8p7K7g44QMgYzLOOHXaganFWWHx6+Og0+2Pjz9ApxmmYGGyv8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=j6VT55xj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="j6VT55xj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 332A3C4AF14; Wed, 3 Jul 2024 22:30:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720045839; bh=acxnBH33pEM3geRn+RlT87+ixutZtG8P8+um1GieHao=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=j6VT55xj8o20WsEyg0kSX/xJCELTFVVxzPJ92MaEmr2HCjGVkx8+sktB+HChuA9qs l8ZxoSo+sLRgGZAcS2bNOOR/LLOYD+cAlEnnuuugul0CdkM6Zcg9N162ScZdkMKMRe CjK9SWB1dSDPd+ppCRbt5C5gYKCjctVfyyRjZC5UZVdRL9rZJj8PqCKneqtACxqqWf 5A7cOkoIJcqVagqxPrtb+aO2kHSogwhx9ErNmzlhuQ9f1PF5xBINq7Xy1mAPodtF5c CQJz7rQq4krgOshqN+a8ZTT1z9SD4FmnGpKfc/tWMLCBo59HIjSBMZf6jWhDwFNSiY rpIiVuYorhvKw== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers , Kan Liang Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, KP Singh , Song Liu , bpf@vger.kernel.org, Stephane Eranian Subject: [PATCH v3 5/8] perf bpf-filter: Support separate lost counts for each filter Date: Wed, 3 Jul 2024 15:30:32 -0700 Message-ID: <20240703223035.2024586-6-namhyung@kernel.org> X-Mailer: git-send-email 2.45.2.803.g4e1b14247a-goog In-Reply-To: <20240703223035.2024586-1-namhyung@kernel.org> References: <20240703223035.2024586-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 As the BPF filter is shared between other processes, it should have its own counter for each invocation. Add a new array map (lost_count) to save the count using the same index as the filter. It should clear the count before running the filter. Signed-off-by: Namhyung Kim --- tools/perf/util/bpf-filter.c | 37 ++++++++++++++++++-- tools/perf/util/bpf_skel/sample_filter.bpf.c | 15 ++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c index 37ed6c48debf..c5eb0b7eec19 100644 --- a/tools/perf/util/bpf-filter.c +++ b/tools/perf/util/bpf-filter.c @@ -260,11 +260,23 @@ int perf_bpf_filter__prepare(struct evsel *evsel, struct target *target) } if (needs_pid_hash && geteuid() != 0) { + int zero = 0; + /* The filters map is shared among other processes */ ret = update_pid_hash(evsel, entry); if (ret < 0) goto err; + fd = get_pinned_fd("dropped"); + if (fd < 0) { + ret = fd; + goto err; + } + + /* Reset the lost count */ + bpf_map_update_elem(fd, &pinned_filter_idx, &zero, BPF_ANY); + close(fd); + fd = get_pinned_fd("perf_sample_filter"); if (fd < 0) { ret = fd; @@ -347,9 +359,25 @@ int perf_bpf_filter__destroy(struct evsel *evsel) u64 perf_bpf_filter__lost_count(struct evsel *evsel) { - struct sample_filter_bpf *skel = evsel->bpf_skel; + int count = 0; + + if (list_empty(&evsel->bpf_filters)) + return 0; + + if (pinned_filter_idx >= 0) { + int fd = get_pinned_fd("dropped"); + + bpf_map_lookup_elem(fd, &pinned_filter_idx, &count); + close(fd); + } else if (evsel->bpf_skel) { + struct sample_filter_bpf *skel = evsel->bpf_skel; + int fd = bpf_map__fd(skel->maps.dropped); + int idx = 0; - return skel ? skel->bss->dropped : 0; + bpf_map_lookup_elem(fd, &idx, &count); + } + + return count; } struct perf_bpf_filter_expr *perf_bpf_filter_expr__new(enum perf_bpf_filter_term term, @@ -402,6 +430,7 @@ int perf_bpf_filter__pin(void) /* pinned program will use pid-hash */ bpf_map__set_max_entries(skel->maps.filters, MAX_FILTERS); bpf_map__set_max_entries(skel->maps.pid_hash, MAX_PIDS); + bpf_map__set_max_entries(skel->maps.dropped, MAX_FILTERS); skel->rodata->use_pid_hash = 1; if (sample_filter_bpf__load(skel) < 0) { @@ -459,6 +488,10 @@ int perf_bpf_filter__pin(void) pr_debug("chmod for pid_hash failed\n"); ret = -errno; } + if (fchmodat(dir_fd, "dropped", 0666, 0) < 0) { + pr_debug("chmod for dropped failed\n"); + ret = -errno; + } err_close: close(dir_fd); diff --git a/tools/perf/util/bpf_skel/sample_filter.bpf.c b/tools/perf/util/bpf_skel/sample_filter.bpf.c index c5273f06fa45..4c75354b84fd 100644 --- a/tools/perf/util/bpf_skel/sample_filter.bpf.c +++ b/tools/perf/util/bpf_skel/sample_filter.bpf.c @@ -23,7 +23,14 @@ struct pid_hash { __uint(max_entries, 1); } pid_hash SEC(".maps"); -int dropped; +/* tgid to filter index */ +struct lost_count { + __uint(type, BPF_MAP_TYPE_ARRAY); + __type(key, int); + __type(value, int); + __uint(max_entries, 1); +} dropped SEC(".maps"); + volatile const int use_pid_hash; void *bpf_cast_to_kern_ctx(void *) __ksym; @@ -189,6 +196,7 @@ int perf_sample_filter(void *ctx) int in_group = 0; int group_result = 0; int i, k; + int *losts; kctx = bpf_cast_to_kern_ctx(ctx); @@ -252,7 +260,10 @@ int perf_sample_filter(void *ctx) return 1; drop: - __sync_fetch_and_add(&dropped, 1); + losts = bpf_map_lookup_elem(&dropped, &k); + if (losts != NULL) + __sync_fetch_and_add(losts, 1); + return 0; } From patchwork Wed Jul 3 22:30:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13722940 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4F7A2194C89; Wed, 3 Jul 2024 22:30:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045840; cv=none; b=kMxjOMevjnGP0UOdIYmflkEXGLo43bunIobUNSTfbx90DHX5IqTzxszhtNTXtBnslQhf5pYOBnDN6EKhDrU7tpU7LWQ+KufGuDME4pXIeTBe2WQxGAmVs+KL8t0GMFeITJnyI8Bmb40fvMsGYBVYn7x2uIt+nSewBiNQW3tqw74= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045840; c=relaxed/simple; bh=kZ93U42Z5rdhAzkA89N6ZJLmQFKP6A1rbOARut3nIvU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HvuIQ/sG0HzmSw3TRk1ZiPa2zodcujOkpN8e7R+i12Cxc3ucguhPP/oypbzzViMPeRmXP5YV2C9CKImA/IpL3U3KlQDoAkxSdrwReALQwRFp3l6WD13aHUFvgU7+h1PJzUcVQ5sNdZ/Wx/i2om90UO5QVTQ9KtxNxQSCigZfWpk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MXi/DYt5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MXi/DYt5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BD8C6C4AF11; Wed, 3 Jul 2024 22:30:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720045840; bh=kZ93U42Z5rdhAzkA89N6ZJLmQFKP6A1rbOARut3nIvU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MXi/DYt59dPOopqj7vtOmRmZvktaiiKTdSmLSuSh8/XfJ93eyT/cpA3aQ9rFV1n1D At8OP7Gl6PAiOgjmuHOTVqhVsutMoqOSGsw689S3zrUlAHRAf6XsqHD34Af6CVOjJ8 Qgv15Vcr6bAGcTX3G9mI1mbb0kDg3670vmL5PN5i0TIOqc3zgyEufUvVMt3+PHsEHs Ub8akaymT7+gIjxryZq7mb6LrTdolnrAr+8vbdnAbXBuSc0vHT6ExC8iz5tQRdJikP AGJubAEnEQqIuvKbEvvRrY78ACxuvoY0bnv2YrbU6iehdrgFfU4y/O0+RZHO45KyQU kz6TKjo6IFUlg== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers , Kan Liang Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, KP Singh , Song Liu , bpf@vger.kernel.org, Stephane Eranian Subject: [PATCH v3 6/8] perf record: Fix a potential error handling issue Date: Wed, 3 Jul 2024 15:30:33 -0700 Message-ID: <20240703223035.2024586-7-namhyung@kernel.org> X-Mailer: git-send-email 2.45.2.803.g4e1b14247a-goog In-Reply-To: <20240703223035.2024586-1-namhyung@kernel.org> References: <20240703223035.2024586-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The evlist is allocated at the beginning of cmd_record(). Also free-ing thread masks should be paired with record__init_thread_masks() which is called right before __cmd_record(). Let's change the order of these functions to release the resources correctly in case of errors. This is maybe fine as the process exits, but it might be a problem if it manages some system-wide resources that live longer than the process. Signed-off-by: Namhyung Kim --- tools/perf/builtin-record.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e855a7688008..a473000f3599 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -4242,13 +4242,13 @@ int cmd_record(int argc, const char **argv) err = __cmd_record(&record, argc, argv); out: - evlist__delete(rec->evlist); + record__free_thread_masks(rec, rec->nr_threads); + rec->nr_threads = 0; symbol__exit(); auxtrace_record__free(rec->itr); out_opts: - record__free_thread_masks(rec, rec->nr_threads); - rec->nr_threads = 0; evlist__close_control(rec->opts.ctl_fd, rec->opts.ctl_fd_ack, &rec->opts.ctl_fd_close); + evlist__delete(rec->evlist); return err; } From patchwork Wed Jul 3 22:30:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13722941 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 30660195FEA; Wed, 3 Jul 2024 22:30:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045841; cv=none; b=sSzSwNr+juW9jPn3GnVmOv7et15LEyk3R5Y0YOGMSwyS6nR6S3J/poyRcPRGXk+NxSA5m2tKz5UlKz+LdE7ofTtMJr05jZu0djnHT1Rn017uVGI8jx+lBzSNoHn0BGwuIK1N5DHEV3lvud38WCN+rd2UdJGDB54IL9K9e3kmcqw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045841; c=relaxed/simple; bh=Oe38Zy3sD1EBtAZsJmD68r+VYxDVmXNUn21vOw1Hj8w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RnrJ8BZ0MGYPwKid7cfpEHaQmF0Oi6OQYH8xZVEIfjNlw+kM5cN+e+bHC/GiqtfQDyhH8i+Kfk5LTD5K8+ZORCO8q4SwckJLEPsVIIuPGDoZMAQPhMi67K5+MX6o0Ni/Mr2YTGVxpmBhD7W5V/U8243rhCUFrMMv7QKNzxholGM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sP6/nJpx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sP6/nJpx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 536E0C4AF0A; Wed, 3 Jul 2024 22:30:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720045840; bh=Oe38Zy3sD1EBtAZsJmD68r+VYxDVmXNUn21vOw1Hj8w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sP6/nJpxO0u8DHPOvnaaBixGb6AsMH1UHhLJe2Ae1xSQDzlE/lAfe1dSyM4LHFbnW vpN2m2vI/2TtVzhVeUczv/tP45Jp45kjQmdemBpjJ86pKAF8386AOPDHS9cP5xEo8u +DY9XOg6YkirHEus4JYb/cwf8eHhqyCD4yMXFFMv42L85wDOLoMdcp50BU3upvpl0Z UvjM1n7CF5VIVScoXQSsnSic70HDOnN7hcXOW+OxQUWQVcVi4ultQuuJD+0gc9ommi 3ZwfPoWxg/tSNH4+22dq6UhO2D2iWw9Ke1kxIajAOzDXDDQOnEVTpzey5SDDeRnxVO Lzr5exwC0qZyw== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers , Kan Liang Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, KP Singh , Song Liu , bpf@vger.kernel.org, Stephane Eranian Subject: [PATCH v3 7/8] perf record: Add --setup-filter option Date: Wed, 3 Jul 2024 15:30:34 -0700 Message-ID: <20240703223035.2024586-8-namhyung@kernel.org> X-Mailer: git-send-email 2.45.2.803.g4e1b14247a-goog In-Reply-To: <20240703223035.2024586-1-namhyung@kernel.org> References: <20240703223035.2024586-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 To allow BPF filters for unprivileged users it needs to pin the BPF objects to BPF-fs first. Let's add a new option to pin and unpin the objects easily. I'm not sure 'perf record' is a right place to do this but I don't have a better idea right now. $ sudo perf record --setup-filter pin The above command would pin BPF program and maps for the filter when the system has BPF-fs (usually at /sys/fs/bpf/). To unpin the objects, users can run the following command (as root). $ sudo perf record --setup-filter unpin Signed-off-by: Namhyung Kim --- tools/perf/Documentation/perf-record.txt | 5 +++++ tools/perf/builtin-record.c | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index d6532ed97c02..41e36b4dc765 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -828,6 +828,11 @@ filtered through the mask provided by -C option. only, as of now. So the applications built without the frame pointer might see bogus addresses. +--setup-filter=:: + Prepare BPF filter to be used by regular users. The action should be + either "pin" or "unpin". The filter can be used after it's pinned. + + include::intel-hybrid.txt[] SEE ALSO diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a473000f3599..e88dedc0391b 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -171,6 +171,7 @@ struct record { bool timestamp_filename; bool timestamp_boundary; bool off_cpu; + const char *filter_action; struct switch_output switch_output; unsigned long long samples; unsigned long output_max_size; /* = 0: unlimited */ @@ -3557,6 +3558,8 @@ static struct option __record_options[] = { "write collected trace data into several data files using parallel threads", record__parse_threads), OPT_BOOLEAN(0, "off-cpu", &record.off_cpu, "Enable off-cpu analysis"), + OPT_STRING(0, "setup-filter", &record.filter_action, "pin|unpin", + "BPF filter action"), OPT_END() }; @@ -4086,6 +4089,18 @@ int cmd_record(int argc, const char **argv) pr_warning("WARNING: --timestamp-filename option is not available in parallel streaming mode.\n"); } + if (rec->filter_action) { + if (!strcmp(rec->filter_action, "pin")) + err = perf_bpf_filter__pin(); + else if (!strcmp(rec->filter_action, "unpin")) + err = perf_bpf_filter__unpin(); + else { + pr_warning("Unknown BPF filter action: %s\n", rec->filter_action); + err = -EINVAL; + } + goto out_opts; + } + /* * Allow aliases to facilitate the lookup of symbols for address * filters. Refer to auxtrace_parse_filters(). From patchwork Wed Jul 3 22:30:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Namhyung Kim X-Patchwork-Id: 13722942 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9E0C3198856; Wed, 3 Jul 2024 22:30:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045841; cv=none; b=bHIsecrjIoOIrA67Cr64Vj2uCHwH7OtCCGiVooQadPGgPG3NZzYVTOw/qMlAdj799GKrDg/nDpxfyv16lolFU9X8+OHq0PVy8vofA3Mgc8H7TTfgVMoeU5wsIPCBCQT6sJY0CC22A0A9QHEHxN71vucsyMNYc9tCT20O8su76m4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720045841; c=relaxed/simple; bh=iNzyG83EiBgTHKgiUVFpdaQFHP6TuBa/IvdNw9r2DAE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DPPMNBMcX6E5RerHMV9L+Pl5HeMiH4pToq9IQWCCmFxFcYvSXGJrP86KrdmUf0vVWS4yaWeLVDpLPBCN+zYXH17B+urimu3peQGInUsWLIhzK9TGdKheD8lwPbYQlbO0Pt76HvNgmTYzB1dAHnYauamTFGnfgbrRWPPXliU9Gys= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=REfrxaSN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="REfrxaSN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DD159C4AF0F; Wed, 3 Jul 2024 22:30:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1720045841; bh=iNzyG83EiBgTHKgiUVFpdaQFHP6TuBa/IvdNw9r2DAE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=REfrxaSNaH9WPtWxsDXh8rJt4mP7rb6SmOUfTYBJvZEnHf4BIaM/OTDH5Va5FOw8e V1gEYdNXvCJ9IWsXnuVTYO/5A3HQ1bJBLUKBVG2W9iWFTbiU4qUfhOTeRQxBjFQF4+ 7isZm7ux1Xi6CYN/YvOj98+U91BOrFzOG/qwhnC3vYckFNfHThlvK3A9lX4DT0NCUW OvhOrQHwFI3GhApQHTiG0x7Z3PX7I2LAou0XhbnzK1ZJlIO7pEE42ldF6z1qKcJ8a/ r8vYtcnrhXjg0I5rOLAjyClluusqjSEXEZWAb+UybE0UW2Mu+twa51gNs09HTL+CX+ JwXkpS+Nh8LIg== From: Namhyung Kim To: Arnaldo Carvalho de Melo , Ian Rogers , Kan Liang Cc: Jiri Olsa , Adrian Hunter , Peter Zijlstra , Ingo Molnar , LKML , linux-perf-users@vger.kernel.org, KP Singh , Song Liu , bpf@vger.kernel.org, Stephane Eranian Subject: [PATCH v3 8/8] perf test: Update sample filtering test Date: Wed, 3 Jul 2024 15:30:35 -0700 Message-ID: <20240703223035.2024586-9-namhyung@kernel.org> X-Mailer: git-send-email 2.45.2.803.g4e1b14247a-goog In-Reply-To: <20240703223035.2024586-1-namhyung@kernel.org> References: <20240703223035.2024586-1-namhyung@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Now it can run the BPF filtering test with normal user if the BPF objects are pinned by 'sudo perf record --setup-filter pin'. Let's update the test case to verify the behavior. It'll skip the test if the filter check is failed from a normal user, but it shows a message how to set up the filters. First, run the test as a normal user and it fails. $ perf test -vv filtering 95: perf record sample filtering (by BPF) tests: --- start --- test child forked, pid 425677 Checking BPF-filter privilege try 'sudo perf record --setup-filter pin' first. <<<--- here bpf-filter test [Skipped permission] ---- end(-2) ---- 95: perf record sample filtering (by BPF) tests : Skip According to the message, run the perf record command to pin the BPF objects. $ sudo perf record --setup-filter pin And re-run the test as a normal user. $ perf test -vv filtering 95: perf record sample filtering (by BPF) tests: --- start --- test child forked, pid 424486 Checking BPF-filter privilege Basic bpf-filter test Basic bpf-filter test [Success] Failing bpf-filter test Error: task-clock event does not have PERF_SAMPLE_CPU Failing bpf-filter test [Success] Group bpf-filter test Error: task-clock event does not have PERF_SAMPLE_CPU Error: task-clock event does not have PERF_SAMPLE_CODE_PAGE_SIZE Group bpf-filter test [Success] ---- end(0) ---- 95: perf record sample filtering (by BPF) tests : Ok Signed-off-by: Namhyung Kim --- tools/perf/tests/shell/record_bpf_filter.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/perf/tests/shell/record_bpf_filter.sh b/tools/perf/tests/shell/record_bpf_filter.sh index 31c593966e8c..c5882d620db7 100755 --- a/tools/perf/tests/shell/record_bpf_filter.sh +++ b/tools/perf/tests/shell/record_bpf_filter.sh @@ -22,15 +22,16 @@ trap trap_cleanup EXIT TERM INT test_bpf_filter_priv() { echo "Checking BPF-filter privilege" - if [ "$(id -u)" != 0 ] - then - echo "bpf-filter test [Skipped permission]" - err=2 - return - fi if ! perf record -e task-clock --filter 'period > 1' \ -o /dev/null --quiet true 2>&1 then + if [ "$(id -u)" != 0 ] + then + echo "try 'sudo perf record --setup-filter pin' first." + echo "bpf-filter test [Skipped permission]" + err=2 + return + fi echo "bpf-filter test [Skipped missing BPF support]" err=2 return