Re: [PATCH bpf-next] selftests/bpf: Move tracing_multi_bench_attach to bench
Andrii Nakryiko <[email protected]> Tue, 4 Aug 2026 15:40:30 -0700
| Newsgroups | org.kernel.vger.linux-kselftest,org.kernel.vger.bpf,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAEf4BzbJCB0KUZMkeRPfYSjMQ3Q3eoFKUZS3px1mBBhxtEqYdQ@mail.gmail.com> |
On Tue, Aug 4, 2026 at 8:48 AM Leon Hwang <[email protected]> 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 <[email protected]> > --- > 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 >