* [PATCH bpf-next] selftests/bpf: Move tracing_multi_bench_attach to bench
@ 2026-08-04 15:48 Leon Hwang
2026-08-04 22:40 ` Andrii Nakryiko
0 siblings, 1 reply; 2+ messages in thread
From: Leon Hwang @ 2026-08-04 15:48 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Ihor Solodrai, Shuah Khan, Leon Hwang, linux-kernel,
linux-kselftest
In CI, the tracing_multi_bench_attach test could cost >10s, which should
be avoided in daily CI running.
./test_progs -t tracing_multi_bench_attach -v
WATCHDOG: test case tracing_multi_bench_attach executes for 10 seconds...
serial_test_tracing_multi_bench_attach: found 40163 functions
serial_test_tracing_multi_bench_attach: attached in 9.367s
serial_test_tracing_multi_bench_attach: detached in 1.798s
#546 tracing_multi_bench_attach:OK
Since it is for benchmark attachment of tracing_multi link, move it to
the generic bench framework.
./bench tracing-multi-attach
Setting up benchmark 'tracing-multi-attach'...
tracing-multi-attach: found 40166 functions
tracing-multi-attach: attached in 9.278s
tracing-multi-attach: detached in 1.836s
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
tools/testing/selftests/bpf/Makefile | 2 +
tools/testing/selftests/bpf/bench.c | 2 +
.../bpf/benchs/bench_tracing_multi_attach.c | 177 ++++++++++++++++++
.../selftests/bpf/prog_tests/tracing_multi.c | 125 -------------
4 files changed, 181 insertions(+), 125 deletions(-)
create mode 100644 tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 55d394438705..e4d8cbd51d71 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -966,6 +966,7 @@ $(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \
$(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h
$(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h
$(OUTPUT)/bench_strncmp.o: $(OUTPUT)/strncmp_bench.skel.h
+$(OUTPUT)/bench_tracing_multi_attach.o: $(OUTPUT)/tracing_multi_bench.skel.h
$(OUTPUT)/bench_bpf_hashmap_full_update.o: $(OUTPUT)/bpf_hashmap_full_update_bench.skel.h
$(OUTPUT)/bench_local_storage.o: $(OUTPUT)/local_storage_bench.skel.h
$(OUTPUT)/bench_local_storage_rcu_tasks_trace.o: $(OUTPUT)/local_storage_rcu_tasks_trace_bench.skel.h
@@ -991,6 +992,7 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \
$(OUTPUT)/bench_bloom_filter_map.o \
$(OUTPUT)/bench_bpf_loop.o \
$(OUTPUT)/bench_strncmp.o \
+ $(OUTPUT)/bench_tracing_multi_attach.o \
$(OUTPUT)/bench_bpf_hashmap_full_update.o \
$(OUTPUT)/bench_local_storage.o \
$(OUTPUT)/bench_local_storage_rcu_tasks_trace.o \
diff --git a/tools/testing/selftests/bpf/bench.c b/tools/testing/selftests/bpf/bench.c
index 3d9d2cd7764b..5ce31459835c 100644
--- a/tools/testing/selftests/bpf/bench.c
+++ b/tools/testing/selftests/bpf/bench.c
@@ -545,6 +545,7 @@ extern const struct bench bench_trig_uprobe_multi_nop5;
extern const struct bench bench_trig_uretprobe_multi_nop5;
extern const struct bench bench_trig_usdt_nop;
extern const struct bench bench_trig_usdt_nop5;
+extern const struct bench bench_tracing_multi_attach;
#endif
extern const struct bench bench_rb_libbpf;
@@ -628,6 +629,7 @@ static const struct bench *benchs[] = {
&bench_trig_uretprobe_multi_nop5,
&bench_trig_usdt_nop,
&bench_trig_usdt_nop5,
+ &bench_tracing_multi_attach,
#endif
/* ringbuf/perfbuf benchmarks */
&bench_rb_libbpf,
diff --git a/tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c b/tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c
new file mode 100644
index 000000000000..7389d1742ddc
--- /dev/null
+++ b/tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <search.h>
+#include <stdio.h>
+#include <string.h>
+#include <bpf/btf.h>
+#include "bench.h"
+#include "testing_helpers.h"
+#include "trace_helpers.h"
+#include "tracing_multi_bench.skel.h"
+#include "bpf/libbpf_internal.h"
+
+static int compare(const void *ppa, const void *ppb)
+{
+ const char *pa = *(const char **)ppa;
+ const char *pb = *(const char **)ppb;
+
+ return strcmp(pa, pb);
+}
+
+static void tdestroy_free_nop(void *ptr)
+{
+}
+
+static void tracing_multi_attach_setup(void)
+{
+ LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
+ struct tracing_multi_bench *skel = NULL;
+ long attach_start_ns, attach_end_ns;
+ long detach_start_ns, detach_end_ns;
+ double attach_delta, detach_delta;
+ struct bpf_link *link = NULL;
+ size_t i, cap = 0, cnt = 0;
+ struct ksyms *ksyms = NULL;
+ void *root = NULL;
+ void *dups = NULL;
+ __u32 *ids = NULL;
+ __u32 nr, type_id;
+ struct btf *btf;
+ int err;
+
+ setup_libbpf();
+
+ btf = btf__load_vmlinux_btf();
+ err = libbpf_get_error(btf);
+ if (err) {
+ btf = NULL;
+ fprintf(stderr, "failed to load vmlinux BTF: %s\n", strerror(-err));
+ goto cleanup;
+ }
+
+ skel = tracing_multi_bench__open_and_load();
+ err = libbpf_get_error(skel);
+ if (!skel) {
+ fprintf(stderr, "failed to open and load skeleton: %s\n", strerror(-err));
+ goto cleanup;
+ }
+
+ err = bpf_get_ksyms(&ksyms, true);
+ if (err) {
+ fprintf(stderr, "failed to get kernel symbols: %s\n", strerror(-err));
+ goto cleanup;
+ }
+
+ /* Get all ftrace 'safe' symbols.. */
+ for (i = 0; i < ksyms->filtered_cnt; i++) {
+ if (!tsearch(&ksyms->filtered_syms[i], &root, compare)) {
+ err = -ENOMEM;
+ fprintf(stderr, "failed to index ftrace symbols\n");
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Collect names that are not unique in kallsyms. The kernel resolves a
+ * tracing-multi BTF id to an address with kallsyms_lookup_name(), which
+ * returns the first symbol of that name. For a duplicate name that may
+ * be a different (non-ftrace-able) instance than the ftrace-able one in
+ * available_filter_functions, so attaching to it by BTF id fails with
+ * -ENOENT (e.g. t_start/t_next/t_stop). ksyms->syms is sorted by name,
+ * so equal names are adjacent.
+ */
+ for (i = 1; i < ksyms->sym_cnt; i++) {
+ if (strcmp(ksyms->syms[i].name, ksyms->syms[i - 1].name))
+ continue;
+ if (!tsearch(&ksyms->syms[i].name, &dups, compare)) {
+ err = -ENOMEM;
+ fprintf(stderr, "failed to index duplicate kernel symbols\n");
+ goto cleanup;
+ }
+ }
+
+ /* ..and filter them through BTF and btf_type_is_traceable_func. */
+ nr = btf__type_cnt(btf);
+ for (type_id = 1; type_id < nr; type_id++) {
+ const struct btf_type *type;
+ const char *str;
+
+ type = btf__type_by_id(btf, type_id);
+ if (!type)
+ break;
+
+ if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC)
+ continue;
+
+ str = btf__name_by_offset(btf, type->name_off);
+ if (!str)
+ break;
+
+ if (!tfind(&str, &root, compare))
+ continue;
+
+ /* Skip names that are not unique in kallsyms, see above. */
+ if (tfind(&str, &dups, compare))
+ continue;
+
+ if (!btf_type_is_traceable_func(btf, type))
+ continue;
+
+ err = libbpf_ensure_mem((void **)&ids, &cap, sizeof(*ids), cnt + 1);
+ if (err) {
+ fprintf(stderr, "failed to allocate BTF ID array: %s\n",
+ strerror(-err));
+ goto cleanup;
+ }
+
+ ids[cnt++] = type_id;
+ }
+
+ opts.ids = ids;
+ opts.cnt = cnt;
+
+ attach_start_ns = get_time_ns();
+ link = bpf_program__attach_tracing_multi(skel->progs.bench, NULL, &opts);
+ attach_end_ns = get_time_ns();
+
+ err = libbpf_get_error(link);
+ if (err) {
+ link = NULL;
+ fprintf(stderr, "failed to attach tracing multi link: %s\n",
+ strerror(-err));
+ goto cleanup;
+ }
+
+ detach_start_ns = get_time_ns();
+ err = bpf_link__destroy(link);
+ detach_end_ns = get_time_ns();
+ link = NULL;
+ if (err) {
+ fprintf(stderr, "failed to detach tracing multi link: %s\n",
+ strerror(-err));
+ goto cleanup;
+ }
+
+ attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0;
+ detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0;
+
+ printf("%s: found %zu functions\n", bench->name, cnt);
+ printf("%s: attached in %7.3lfs\n", bench->name, attach_delta);
+ printf("%s: detached in %7.3lfs\n", bench->name, detach_delta);
+
+cleanup:
+ bpf_link__destroy(link);
+ tracing_multi_bench__destroy(skel);
+ tdestroy(root, tdestroy_free_nop);
+ tdestroy(dups, tdestroy_free_nop);
+ free_kallsyms_local(ksyms);
+ free(ids);
+ btf__free(btf);
+
+ exit(err ? 1 : 0);
+}
+
+const struct bench bench_tracing_multi_attach = {
+ .name = "tracing-multi-attach",
+ .setup = tracing_multi_attach_setup,
+};
diff --git a/tools/testing/selftests/bpf/prog_tests/tracing_multi.c b/tools/testing/selftests/bpf/prog_tests/tracing_multi.c
index 0aa9532a05cf..fd4f256d2e0a 100644
--- a/tools/testing/selftests/bpf/prog_tests/tracing_multi.c
+++ b/tools/testing/selftests/bpf/prog_tests/tracing_multi.c
@@ -3,14 +3,12 @@
#include <test_progs.h>
#include <bpf/btf.h>
#include <search.h>
-#include "bpf/libbpf_internal.h"
#include "tracing_multi.skel.h"
#include "tracing_multi_module.skel.h"
#include "tracing_multi_intersect.skel.h"
#include "tracing_multi_session.skel.h"
#include "tracing_multi_fail.skel.h"
#include "tracing_multi_verifier.skel.h"
-#include "tracing_multi_bench.skel.h"
#include "tracing_multi_rollback.skel.h"
#include "trace_helpers.h"
@@ -662,129 +660,6 @@ static void test_attach_api_fails(void)
free(ids2);
}
-void serial_test_tracing_multi_bench_attach(void)
-{
- LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
- struct tracing_multi_bench *skel = NULL;
- long attach_start_ns, attach_end_ns;
- long detach_start_ns, detach_end_ns;
- double attach_delta, detach_delta;
- struct bpf_link *link = NULL;
- size_t i, cap = 0, cnt = 0;
- struct ksyms *ksyms = NULL;
- void *root = NULL;
- void *dups = NULL;
- __u32 *ids = NULL;
- __u32 nr, type_id;
- struct btf *btf;
- int err;
-
-#ifndef __x86_64__
- test__skip();
- return;
-#endif
-
- btf = btf__load_vmlinux_btf();
- if (!ASSERT_OK_PTR(btf, "btf__load_vmlinux_btf"))
- return;
-
- skel = tracing_multi_bench__open_and_load();
- if (!ASSERT_OK_PTR(skel, "tracing_multi_bench__open_and_load"))
- goto cleanup;
-
- if (!ASSERT_OK(bpf_get_ksyms(&ksyms, true), "get_syms"))
- goto cleanup;
-
- /* Get all ftrace 'safe' symbols.. */
- for (i = 0; i < ksyms->filtered_cnt; i++) {
- if (!tsearch(&ksyms->filtered_syms[i], &root, compare)) {
- ASSERT_FAIL("tsearch failed");
- goto cleanup;
- }
- }
-
- /*
- * Collect names that are not unique in kallsyms. The kernel resolves a
- * tracing-multi BTF id to an address with kallsyms_lookup_name(), which
- * returns the first symbol of that name. For a duplicate name that may
- * be a different (non-ftrace-able) instance than the ftrace-able one in
- * available_filter_functions, so attaching to it by BTF id fails with
- * -ENOENT (e.g. t_start/t_next/t_stop). ksyms->syms is sorted by name,
- * so equal names are adjacent.
- */
- for (i = 1; i < ksyms->sym_cnt; i++) {
- if (strcmp(ksyms->syms[i].name, ksyms->syms[i - 1].name))
- continue;
- if (!tsearch(&ksyms->syms[i].name, &dups, compare)) {
- ASSERT_FAIL("tsearch failed");
- goto cleanup;
- }
- }
-
- /* ..and filter them through BTF and btf_type_is_traceable_func. */
- nr = btf__type_cnt(btf);
- for (type_id = 1; type_id < nr; type_id++) {
- const struct btf_type *type;
- const char *str;
-
- type = btf__type_by_id(btf, type_id);
- if (!type)
- break;
-
- if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC)
- continue;
-
- str = btf__name_by_offset(btf, type->name_off);
- if (!str)
- break;
-
- if (!tfind(&str, &root, compare))
- continue;
-
- /* Skip names that are not unique in kallsyms, see above. */
- if (tfind(&str, &dups, compare))
- continue;
-
- if (!btf_type_is_traceable_func(btf, type))
- continue;
-
- err = libbpf_ensure_mem((void **) &ids, &cap, sizeof(*ids), cnt + 1);
- if (err)
- goto cleanup;
-
- ids[cnt++] = type_id;
- }
-
- opts.ids = ids;
- opts.cnt = cnt;
-
- attach_start_ns = get_time_ns();
- link = bpf_program__attach_tracing_multi(skel->progs.bench, NULL, &opts);
- attach_end_ns = get_time_ns();
-
- if (!ASSERT_OK_PTR(link, "bpf_program__attach_tracing_multi"))
- goto cleanup;
-
- detach_start_ns = get_time_ns();
- bpf_link__destroy(link);
- detach_end_ns = get_time_ns();
-
- attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0;
- detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0;
-
- printf("%s: found %lu functions\n", __func__, cnt);
- printf("%s: attached in %7.3lfs\n", __func__, attach_delta);
- printf("%s: detached in %7.3lfs\n", __func__, detach_delta);
-
-cleanup:
- tracing_multi_bench__destroy(skel);
- tdestroy(root, tdestroy_free_nop);
- tdestroy(dups, tdestroy_free_nop);
- free_kallsyms_local(ksyms);
- free(ids);
- btf__free(btf);
-}
-
static void tracing_multi_rollback_run(struct tracing_multi_rollback *skel)
{
LIBBPF_OPTS(bpf_test_run_opts, topts);
--
2.55.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH bpf-next] selftests/bpf: Move tracing_multi_bench_attach to bench
2026-08-04 15:48 [PATCH bpf-next] selftests/bpf: Move tracing_multi_bench_attach to bench Leon Hwang
@ 2026-08-04 22:40 ` Andrii Nakryiko
0 siblings, 0 replies; 2+ messages in thread
From: Andrii Nakryiko @ 2026-08-04 22:40 UTC (permalink / raw)
To: Leon Hwang, Jiri Olsa
Cc: bpf, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Emil Tsalapatis, Ihor Solodrai,
Shuah Khan, linux-kernel, linux-kselftest
On Tue, Aug 4, 2026 at 8:48 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> In CI, the tracing_multi_bench_attach test could cost >10s, which should
> be avoided in daily CI running.
>
> ./test_progs -t tracing_multi_bench_attach -v
> WATCHDOG: test case tracing_multi_bench_attach executes for 10 seconds...
> serial_test_tracing_multi_bench_attach: found 40163 functions
> serial_test_tracing_multi_bench_attach: attached in 9.367s
> serial_test_tracing_multi_bench_attach: detached in 1.798s
> #546 tracing_multi_bench_attach:OK
>
> Since it is for benchmark attachment of tracing_multi link, move it to
> the generic bench framework.
>
> ./bench tracing-multi-attach
> Setting up benchmark 'tracing-multi-attach'...
> tracing-multi-attach: found 40166 functions
> tracing-multi-attach: attached in 9.278s
> tracing-multi-attach: detached in 1.836s
>
> Assisted-by: Codex:gpt-5.6-sol
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
> ---
> tools/testing/selftests/bpf/Makefile | 2 +
> tools/testing/selftests/bpf/bench.c | 2 +
> .../bpf/benchs/bench_tracing_multi_attach.c | 177 ++++++++++++++++++
> .../selftests/bpf/prog_tests/tracing_multi.c | 125 -------------
> 4 files changed, 181 insertions(+), 125 deletions(-)
> create mode 100644 tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c
>
Jiri, are you ok with not exercising this logic regularly?
but also hm, is 10 seconds expected?
> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> index 55d394438705..e4d8cbd51d71 100644
> --- a/tools/testing/selftests/bpf/Makefile
> +++ b/tools/testing/selftests/bpf/Makefile
> @@ -966,6 +966,7 @@ $(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \
> $(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h
> $(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h
> $(OUTPUT)/bench_strncmp.o: $(OUTPUT)/strncmp_bench.skel.h
> +$(OUTPUT)/bench_tracing_multi_attach.o: $(OUTPUT)/tracing_multi_bench.skel.h
> $(OUTPUT)/bench_bpf_hashmap_full_update.o: $(OUTPUT)/bpf_hashmap_full_update_bench.skel.h
> $(OUTPUT)/bench_local_storage.o: $(OUTPUT)/local_storage_bench.skel.h
> $(OUTPUT)/bench_local_storage_rcu_tasks_trace.o: $(OUTPUT)/local_storage_rcu_tasks_trace_bench.skel.h
> @@ -991,6 +992,7 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \
> $(OUTPUT)/bench_bloom_filter_map.o \
> $(OUTPUT)/bench_bpf_loop.o \
> $(OUTPUT)/bench_strncmp.o \
> + $(OUTPUT)/bench_tracing_multi_attach.o \
> $(OUTPUT)/bench_bpf_hashmap_full_update.o \
> $(OUTPUT)/bench_local_storage.o \
> $(OUTPUT)/bench_local_storage_rcu_tasks_trace.o \
> diff --git a/tools/testing/selftests/bpf/bench.c b/tools/testing/selftests/bpf/bench.c
> index 3d9d2cd7764b..5ce31459835c 100644
> --- a/tools/testing/selftests/bpf/bench.c
> +++ b/tools/testing/selftests/bpf/bench.c
> @@ -545,6 +545,7 @@ extern const struct bench bench_trig_uprobe_multi_nop5;
> extern const struct bench bench_trig_uretprobe_multi_nop5;
> extern const struct bench bench_trig_usdt_nop;
> extern const struct bench bench_trig_usdt_nop5;
> +extern const struct bench bench_tracing_multi_attach;
> #endif
>
> extern const struct bench bench_rb_libbpf;
> @@ -628,6 +629,7 @@ static const struct bench *benchs[] = {
> &bench_trig_uretprobe_multi_nop5,
> &bench_trig_usdt_nop,
> &bench_trig_usdt_nop5,
> + &bench_tracing_multi_attach,
> #endif
> /* ringbuf/perfbuf benchmarks */
> &bench_rb_libbpf,
> diff --git a/tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c b/tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c
> new file mode 100644
> index 000000000000..7389d1742ddc
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/benchs/bench_tracing_multi_attach.c
> @@ -0,0 +1,177 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#define _GNU_SOURCE
> +#include <search.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <bpf/btf.h>
> +#include "bench.h"
> +#include "testing_helpers.h"
> +#include "trace_helpers.h"
> +#include "tracing_multi_bench.skel.h"
> +#include "bpf/libbpf_internal.h"
> +
> +static int compare(const void *ppa, const void *ppb)
> +{
> + const char *pa = *(const char **)ppa;
> + const char *pb = *(const char **)ppb;
> +
> + return strcmp(pa, pb);
> +}
> +
> +static void tdestroy_free_nop(void *ptr)
> +{
> +}
> +
> +static void tracing_multi_attach_setup(void)
> +{
> + LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
> + struct tracing_multi_bench *skel = NULL;
> + long attach_start_ns, attach_end_ns;
> + long detach_start_ns, detach_end_ns;
> + double attach_delta, detach_delta;
> + struct bpf_link *link = NULL;
> + size_t i, cap = 0, cnt = 0;
> + struct ksyms *ksyms = NULL;
> + void *root = NULL;
> + void *dups = NULL;
> + __u32 *ids = NULL;
> + __u32 nr, type_id;
> + struct btf *btf;
> + int err;
> +
> + setup_libbpf();
> +
> + btf = btf__load_vmlinux_btf();
> + err = libbpf_get_error(btf);
> + if (err) {
> + btf = NULL;
> + fprintf(stderr, "failed to load vmlinux BTF: %s\n", strerror(-err));
> + goto cleanup;
> + }
> +
> + skel = tracing_multi_bench__open_and_load();
> + err = libbpf_get_error(skel);
> + if (!skel) {
> + fprintf(stderr, "failed to open and load skeleton: %s\n", strerror(-err));
> + goto cleanup;
> + }
> +
> + err = bpf_get_ksyms(&ksyms, true);
> + if (err) {
> + fprintf(stderr, "failed to get kernel symbols: %s\n", strerror(-err));
> + goto cleanup;
> + }
> +
> + /* Get all ftrace 'safe' symbols.. */
> + for (i = 0; i < ksyms->filtered_cnt; i++) {
> + if (!tsearch(&ksyms->filtered_syms[i], &root, compare)) {
> + err = -ENOMEM;
> + fprintf(stderr, "failed to index ftrace symbols\n");
> + goto cleanup;
> + }
> + }
> +
> + /*
> + * Collect names that are not unique in kallsyms. The kernel resolves a
> + * tracing-multi BTF id to an address with kallsyms_lookup_name(), which
> + * returns the first symbol of that name. For a duplicate name that may
> + * be a different (non-ftrace-able) instance than the ftrace-able one in
> + * available_filter_functions, so attaching to it by BTF id fails with
> + * -ENOENT (e.g. t_start/t_next/t_stop). ksyms->syms is sorted by name,
> + * so equal names are adjacent.
> + */
> + for (i = 1; i < ksyms->sym_cnt; i++) {
> + if (strcmp(ksyms->syms[i].name, ksyms->syms[i - 1].name))
> + continue;
> + if (!tsearch(&ksyms->syms[i].name, &dups, compare)) {
> + err = -ENOMEM;
> + fprintf(stderr, "failed to index duplicate kernel symbols\n");
> + goto cleanup;
> + }
> + }
> +
> + /* ..and filter them through BTF and btf_type_is_traceable_func. */
> + nr = btf__type_cnt(btf);
> + for (type_id = 1; type_id < nr; type_id++) {
> + const struct btf_type *type;
> + const char *str;
> +
> + type = btf__type_by_id(btf, type_id);
> + if (!type)
> + break;
> +
> + if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC)
> + continue;
> +
> + str = btf__name_by_offset(btf, type->name_off);
> + if (!str)
> + break;
> +
> + if (!tfind(&str, &root, compare))
> + continue;
> +
> + /* Skip names that are not unique in kallsyms, see above. */
> + if (tfind(&str, &dups, compare))
> + continue;
> +
> + if (!btf_type_is_traceable_func(btf, type))
> + continue;
> +
> + err = libbpf_ensure_mem((void **)&ids, &cap, sizeof(*ids), cnt + 1);
> + if (err) {
> + fprintf(stderr, "failed to allocate BTF ID array: %s\n",
> + strerror(-err));
> + goto cleanup;
> + }
> +
> + ids[cnt++] = type_id;
> + }
> +
> + opts.ids = ids;
> + opts.cnt = cnt;
> +
> + attach_start_ns = get_time_ns();
> + link = bpf_program__attach_tracing_multi(skel->progs.bench, NULL, &opts);
> + attach_end_ns = get_time_ns();
> +
> + err = libbpf_get_error(link);
> + if (err) {
> + link = NULL;
> + fprintf(stderr, "failed to attach tracing multi link: %s\n",
> + strerror(-err));
> + goto cleanup;
> + }
> +
> + detach_start_ns = get_time_ns();
> + err = bpf_link__destroy(link);
> + detach_end_ns = get_time_ns();
> + link = NULL;
> + if (err) {
> + fprintf(stderr, "failed to detach tracing multi link: %s\n",
> + strerror(-err));
> + goto cleanup;
> + }
> +
> + attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0;
> + detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0;
> +
> + printf("%s: found %zu functions\n", bench->name, cnt);
> + printf("%s: attached in %7.3lfs\n", bench->name, attach_delta);
> + printf("%s: detached in %7.3lfs\n", bench->name, detach_delta);
> +
> +cleanup:
> + bpf_link__destroy(link);
> + tracing_multi_bench__destroy(skel);
> + tdestroy(root, tdestroy_free_nop);
> + tdestroy(dups, tdestroy_free_nop);
> + free_kallsyms_local(ksyms);
> + free(ids);
> + btf__free(btf);
> +
> + exit(err ? 1 : 0);
> +}
> +
> +const struct bench bench_tracing_multi_attach = {
> + .name = "tracing-multi-attach",
> + .setup = tracing_multi_attach_setup,
> +};
> diff --git a/tools/testing/selftests/bpf/prog_tests/tracing_multi.c b/tools/testing/selftests/bpf/prog_tests/tracing_multi.c
> index 0aa9532a05cf..fd4f256d2e0a 100644
> --- a/tools/testing/selftests/bpf/prog_tests/tracing_multi.c
> +++ b/tools/testing/selftests/bpf/prog_tests/tracing_multi.c
> @@ -3,14 +3,12 @@
> #include <test_progs.h>
> #include <bpf/btf.h>
> #include <search.h>
> -#include "bpf/libbpf_internal.h"
> #include "tracing_multi.skel.h"
> #include "tracing_multi_module.skel.h"
> #include "tracing_multi_intersect.skel.h"
> #include "tracing_multi_session.skel.h"
> #include "tracing_multi_fail.skel.h"
> #include "tracing_multi_verifier.skel.h"
> -#include "tracing_multi_bench.skel.h"
> #include "tracing_multi_rollback.skel.h"
> #include "trace_helpers.h"
>
> @@ -662,129 +660,6 @@ static void test_attach_api_fails(void)
> free(ids2);
> }
>
> -void serial_test_tracing_multi_bench_attach(void)
> -{
> - LIBBPF_OPTS(bpf_tracing_multi_opts, opts);
> - struct tracing_multi_bench *skel = NULL;
> - long attach_start_ns, attach_end_ns;
> - long detach_start_ns, detach_end_ns;
> - double attach_delta, detach_delta;
> - struct bpf_link *link = NULL;
> - size_t i, cap = 0, cnt = 0;
> - struct ksyms *ksyms = NULL;
> - void *root = NULL;
> - void *dups = NULL;
> - __u32 *ids = NULL;
> - __u32 nr, type_id;
> - struct btf *btf;
> - int err;
> -
> -#ifndef __x86_64__
> - test__skip();
> - return;
> -#endif
> -
> - btf = btf__load_vmlinux_btf();
> - if (!ASSERT_OK_PTR(btf, "btf__load_vmlinux_btf"))
> - return;
> -
> - skel = tracing_multi_bench__open_and_load();
> - if (!ASSERT_OK_PTR(skel, "tracing_multi_bench__open_and_load"))
> - goto cleanup;
> -
> - if (!ASSERT_OK(bpf_get_ksyms(&ksyms, true), "get_syms"))
> - goto cleanup;
> -
> - /* Get all ftrace 'safe' symbols.. */
> - for (i = 0; i < ksyms->filtered_cnt; i++) {
> - if (!tsearch(&ksyms->filtered_syms[i], &root, compare)) {
> - ASSERT_FAIL("tsearch failed");
> - goto cleanup;
> - }
> - }
> -
> - /*
> - * Collect names that are not unique in kallsyms. The kernel resolves a
> - * tracing-multi BTF id to an address with kallsyms_lookup_name(), which
> - * returns the first symbol of that name. For a duplicate name that may
> - * be a different (non-ftrace-able) instance than the ftrace-able one in
> - * available_filter_functions, so attaching to it by BTF id fails with
> - * -ENOENT (e.g. t_start/t_next/t_stop). ksyms->syms is sorted by name,
> - * so equal names are adjacent.
> - */
> - for (i = 1; i < ksyms->sym_cnt; i++) {
> - if (strcmp(ksyms->syms[i].name, ksyms->syms[i - 1].name))
> - continue;
> - if (!tsearch(&ksyms->syms[i].name, &dups, compare)) {
> - ASSERT_FAIL("tsearch failed");
> - goto cleanup;
> - }
> - }
> -
> - /* ..and filter them through BTF and btf_type_is_traceable_func. */
> - nr = btf__type_cnt(btf);
> - for (type_id = 1; type_id < nr; type_id++) {
> - const struct btf_type *type;
> - const char *str;
> -
> - type = btf__type_by_id(btf, type_id);
> - if (!type)
> - break;
> -
> - if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC)
> - continue;
> -
> - str = btf__name_by_offset(btf, type->name_off);
> - if (!str)
> - break;
> -
> - if (!tfind(&str, &root, compare))
> - continue;
> -
> - /* Skip names that are not unique in kallsyms, see above. */
> - if (tfind(&str, &dups, compare))
> - continue;
> -
> - if (!btf_type_is_traceable_func(btf, type))
> - continue;
> -
> - err = libbpf_ensure_mem((void **) &ids, &cap, sizeof(*ids), cnt + 1);
> - if (err)
> - goto cleanup;
> -
> - ids[cnt++] = type_id;
> - }
> -
> - opts.ids = ids;
> - opts.cnt = cnt;
> -
> - attach_start_ns = get_time_ns();
> - link = bpf_program__attach_tracing_multi(skel->progs.bench, NULL, &opts);
> - attach_end_ns = get_time_ns();
> -
> - if (!ASSERT_OK_PTR(link, "bpf_program__attach_tracing_multi"))
> - goto cleanup;
> -
> - detach_start_ns = get_time_ns();
> - bpf_link__destroy(link);
> - detach_end_ns = get_time_ns();
> -
> - attach_delta = (attach_end_ns - attach_start_ns) / 1000000000.0;
> - detach_delta = (detach_end_ns - detach_start_ns) / 1000000000.0;
> -
> - printf("%s: found %lu functions\n", __func__, cnt);
> - printf("%s: attached in %7.3lfs\n", __func__, attach_delta);
> - printf("%s: detached in %7.3lfs\n", __func__, detach_delta);
> -
> -cleanup:
> - tracing_multi_bench__destroy(skel);
> - tdestroy(root, tdestroy_free_nop);
> - tdestroy(dups, tdestroy_free_nop);
> - free_kallsyms_local(ksyms);
> - free(ids);
> - btf__free(btf);
> -}
> -
> static void tracing_multi_rollback_run(struct tracing_multi_rollback *skel)
> {
> LIBBPF_OPTS(bpf_test_run_opts, topts);
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-04 22:40 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-04 15:48 [PATCH bpf-next] selftests/bpf: Move tracing_multi_bench_attach to bench Leon Hwang
2026-08-04 22:40 ` Andrii Nakryiko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox