]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests/bpf: Add tracing multi attach benchmark test
authorJiri Olsa <jolsa@kernel.org>
Sat, 6 Jun 2026 12:39:53 +0000 (14:39 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Sun, 7 Jun 2026 18:02:04 +0000 (11:02 -0700)
Adding benchmark test that attaches to (almost) all allowed tracing
functions and display attach/detach times.

  # ./test_progs -t tracing_multi_bench_attach -v
  bpf_testmod.ko is already unloaded.
  Loading bpf_testmod.ko...
  Successfully loaded bpf_testmod.ko.
  serial_test_tracing_multi_bench_attach:PASS:btf__load_vmlinux_btf 0 nsec
  serial_test_tracing_multi_bench_attach:PASS:tracing_multi_bench__open_and_load 0 nsec
  serial_test_tracing_multi_bench_attach:PASS:get_syms 0 nsec
  serial_test_tracing_multi_bench_attach:PASS:bpf_program__attach_tracing_multi 0 nsec
  serial_test_tracing_multi_bench_attach: found 51186 functions
  serial_test_tracing_multi_bench_attach: attached in   1.295s
  serial_test_tracing_multi_bench_attach: detached in   0.243s
  #507     tracing_multi_bench_attach:OK
  Summary: 1/0 PASSED, 0 SKIPPED, 0 FAILED
  Successfully unloaded bpf_testmod.ko.

Exporting skip_entry as is_unsafe_function and using it in the test.

Also updating trace_blacklist with ___migrate_enable to be in sync
with kernel functions deny list.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20260606123955.345967-29-jolsa@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/prog_tests/tracing_multi.c
tools/testing/selftests/bpf/progs/tracing_multi_bench.c [new file with mode: 0644]
tools/testing/selftests/bpf/trace_helpers.c
tools/testing/selftests/bpf/trace_helpers.h

index 9e026f2b254d0b365a1073016e3ddae0cc30570c..cb39bf6108238542d28b6a3a10336f84bc90907f 100644 (file)
@@ -10,6 +10,7 @@
 #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 "trace_helpers.h"
 
 static __u64 bpf_fentry_test_cookies[] = {
@@ -593,6 +594,129 @@ cleanup:
        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);
+}
+
 void test_tracing_multi_test(void)
 {
 #ifndef __x86_64__
diff --git a/tools/testing/selftests/bpf/progs/tracing_multi_bench.c b/tools/testing/selftests/bpf/progs/tracing_multi_bench.c
new file mode 100644 (file)
index 0000000..beae946
--- /dev/null
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+SEC("fentry.multi")
+int BPF_PROG(bench)
+{
+       return 0;
+}
index 0e63daf83ed52bc599ec685985b5bd7b023e1693..679008b310d9a1391eb636bbe77552cef0f32750 100644 (file)
@@ -546,9 +546,10 @@ static const char * const trace_blacklist[] = {
        "__rcu_read_lock",
        "__rcu_read_unlock",
        "bpf_get_numa_node_id",
+       "___migrate_enable",
 };
 
-static bool skip_entry(char *name)
+bool is_unsafe_function(const char *name)
 {
        int i;
 
@@ -651,7 +652,7 @@ int bpf_get_ksyms(struct ksyms **ksymsp, bool kernel)
                free(name);
                if (sscanf(buf, "%ms$*[^\n]\n", &name) != 1)
                        continue;
-               if (skip_entry(name))
+               if (is_unsafe_function(name))
                        continue;
 
                ks = search_kallsyms_custom_local(ksyms, name, search_kallsyms_compare);
@@ -728,7 +729,7 @@ int bpf_get_addrs(unsigned long **addrsp, size_t *cntp, bool kernel)
                free(name);
                if (sscanf(buf, "%p %ms$*[^\n]\n", &addr, &name) != 2)
                        continue;
-               if (skip_entry(name))
+               if (is_unsafe_function(name))
                        continue;
 
                if (cnt == max_cnt) {
index d5bf1433675d66f4ee8994bdf60b8a0c17133fb6..01c8ecc4562706252b9754235fc87dd32e0eae01 100644 (file)
@@ -63,4 +63,5 @@ int read_build_id(const char *path, char *build_id, size_t size);
 int bpf_get_ksyms(struct ksyms **ksymsp, bool kernel);
 int bpf_get_addrs(unsigned long **addrsp, size_t *cntp, bool kernel);
 
+bool is_unsafe_function(const char *name);
 #endif