mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH bpf-next v4 0/2] libbpf: Improve BPF load performance by selectively loading kmod BTFs
@ 2026-08-24 12:53 Fuyu Zhao
  2026-08-24 12:53 ` [PATCH bpf-next v4 1/2] libbpf: support selective kernel module BTF loading via bpf_object_open_opts Fuyu Zhao
  2026-08-24 12:53 ` [PATCH bpf-next v4 2/2] selftests/bpf: add tests for selective module BTF loading Fuyu Zhao
  0 siblings, 2 replies; 5+ messages in thread
From: Fuyu Zhao @ 2026-08-24 12:53 UTC (permalink / raw)
  To: bpf, eddyz87, andrii.nakryiko, alan.maguire
  Cc: andrii, ast, daniel, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, shuah, yatsenko, linux-kernel,
	linux-kselftest, Fuyu Zhao

Currently, during BPF object loading, load_module_btfs() unconditionally
iterates over all kernel module BTFs and loads each one. This introduces
unnecessary overhead when a BPF program only needs BTFs from a specific,
small subset of modules. In environments with hundreds of modules,
loading all module BTFs can measurably increase the loading time.

In our Android testing, BPF programs are loaded on demand rather than
preloaded to avoid unnecessary memory usage from unused programs. With
93 module BTFs present, the total BPF loading time exceeds 300 ms, with
module BTF loading accounting for around 69% of the total loading time.

The existing module qualification in SEC(), such as
SEC("fentry/mymod:foo"), does not address this issue. It only affects
BTF ID lookup after module BTFs have already been loaded by
load_module_btfs(), and does not reduce the number of module BTFs loaded.

This series adds btf_module_names and nr_btf_module_names fields to
bpf_object_open_opts, allowing users to specify a list of kernel modules
whose BTFs should be loaded. libbpf uses this information to skip
unrelated module BTFs during iteration and stops iterating once all
requested module BTFs have been loaded. Without these options, the
existing behavior remains unchanged.

Performance impact (BPF skeleton open and load time):

  Modules loaded | Default (load all) | With btf_module_names | Speedup
  ---------------|--------------------|-----------------------|--------
  1              | 35.6 ms            | 35.6 ms               | Baseline
  10             | 37.2 ms            | 35.7 ms               | +4.0%
  100            | 46.7 ms            | 36.5 ms               | +21.8%
  300            | 65.2 ms            | 38.5 ms               | +40.9%

Changelog:
v4:
- Simplify and rename newly added struct members and their documentation.
  (Eduard)
- Use array search instead of a hashmap for module name matching to
  simplify the code. (Eduard)
- Allow an empty module name list to skip loading all module BTFs.
  (Eduard, sashiko-bot)
- Move btf_module_names option handling before bpf_object__elf_init().
  (Eduard)
- Rename internal helpers to follow libbpf naming conventions. (Andrii)
- Reject duplicate module names and document the rejection rule. (Andrii)
- Replace log interception with functional tests and simplify selftests.
  (Andrii)

v3:
- Link: https://lore.kernel.org/bpf/20260819090426.267-1-zhaofuyu@vivo.com/
- Use bpf_object_open_opts to specify kernel module BTFs to load rather
  than introducing a new .kmod_btfs ELF section, as suggested by Andrii.

v2:
- Link: https://lore.kernel.org/bpf/20260813032613.2755-1-zhaofuyu@vivo.com/
- Addressed issues with allocation error handling, multiple .kmod_btfs
  sections, the transient stack pointer in is_kmod_btf_needed(), and
  selftest dependency and comment formatting. (sashiko-bot)
- Removed KMODS_BTF_LOADED and KMODS_BTF_UNLOADED and simplified the
  related logic.

v1:
- Link: https://lore.kernel.org/bpf/20260806042042.3239428-1-zhaofuyu@vivo.com/

Fuyu Zhao (2):
  libbpf: support selective kernel module BTF loading via
    bpf_object_open_opts
  selftests/bpf: add tests for selective module BTF loading

 tools/lib/bpf/libbpf.c                        | 105 ++++++++++++++++++
 tools/lib/bpf/libbpf.h                        |  24 +++-
 .../bpf/prog_tests/btf_module_names.c         |  93 ++++++++++++++++
 .../selftests/bpf/progs/btf_module_names.c    |  13 +++
 4 files changed, 234 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_module_names.c
 create mode 100644 tools/testing/selftests/bpf/progs/btf_module_names.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH bpf-next v4 1/2] libbpf: support selective kernel module BTF loading via bpf_object_open_opts
  2026-08-24 12:53 [PATCH bpf-next v4 0/2] libbpf: Improve BPF load performance by selectively loading kmod BTFs Fuyu Zhao
@ 2026-08-24 12:53 ` Fuyu Zhao
  2026-08-24 13:31   ` bot+bpf-ci
  2026-08-24 12:53 ` [PATCH bpf-next v4 2/2] selftests/bpf: add tests for selective module BTF loading Fuyu Zhao
  1 sibling, 1 reply; 5+ messages in thread
From: Fuyu Zhao @ 2026-08-24 12:53 UTC (permalink / raw)
  To: bpf, eddyz87, andrii.nakryiko, alan.maguire
  Cc: andrii, ast, daniel, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, shuah, yatsenko, linux-kernel,
	linux-kselftest, Fuyu Zhao

Add btf_module_names and nr_btf_module_names fields to
bpf_object_open_opts to support selective kernel module BTF loading.

When btf_module_names is provided, libbpf loads BTFs only for the
specified kernel modules and skips other module BTFs. If
btf_module_names is NULL, all module BTFs are loaded as before.

This avoids unnecessary module BTF loading and reduces BPF object
loading time when only a subset of kernel module BTFs is needed.

Suggested-by: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Signed-off-by: Fuyu Zhao <zhaofuyu@vivo.com>
---
 tools/lib/bpf/libbpf.c | 105 +++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  24 +++++++++-
 2 files changed, 128 insertions(+), 1 deletion(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 514e4e9daa82..6f5d3213b3e5 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -779,6 +779,9 @@ struct bpf_object {
 	char *token_path;
 	int token_fd;
 
+	char **btf_module_names;
+	size_t nr_btf_module_names;
+
 	char path[];
 };
 
@@ -5803,6 +5806,94 @@ int bpf_core_add_cands(struct bpf_core_cand *local_cand,
 	return 0;
 }
 
+static void bpf_object_free_btf_module_names(struct bpf_object *obj)
+{
+	size_t i;
+
+	if (!obj->btf_module_names)
+		return;
+
+	for (i = 0; i < obj->nr_btf_module_names; i++)
+		zfree(&obj->btf_module_names[i]);
+	zfree(&obj->btf_module_names);
+	obj->nr_btf_module_names = 0;
+}
+
+static int bpf_object_init_btf_module_names(struct bpf_object *obj,
+					    const struct bpf_object_open_opts *opts)
+{
+	const char **names;
+	size_t i, j, cnt;
+	int err;
+
+	names = OPTS_GET(opts, btf_module_names, NULL);
+	if (!names)
+		return 0;
+
+	cnt = OPTS_GET(opts, nr_btf_module_names, 0);
+
+	/*
+	 * Keep btf_module_names non-NULL to distinguish an empty filter from
+	 * the default behavior of loading all module BTFs.
+	 */
+	obj->btf_module_names = calloc(cnt ?: 1,
+				       sizeof(*obj->btf_module_names));
+	if (!obj->btf_module_names)
+		return -ENOMEM;
+
+	for (i = 0; i < cnt; i++) {
+		if (!names[i] || !names[i][0]) {
+			pr_warn("invalid kernel module BTF name at index %zu\n", i);
+			err = -EINVAL;
+			goto err_out;
+		}
+
+		for (j = 0; j < i; j++) {
+			if (strcmp(obj->btf_module_names[j], names[i]) == 0) {
+				pr_warn("duplicate kernel module BTF name '%s'\n",
+					names[i]);
+				err = -EINVAL;
+				goto err_out;
+			}
+		}
+
+		obj->btf_module_names[i] = strdup(names[i]);
+		if (!obj->btf_module_names[i]) {
+			err = -ENOMEM;
+			goto err_out;
+		}
+
+		obj->nr_btf_module_names++;
+	}
+	return 0;
+
+err_out:
+	bpf_object_free_btf_module_names(obj);
+	return err;
+}
+
+static bool is_module_btf_needed(const struct bpf_object *obj, const char *name)
+{
+	size_t i;
+
+	if (!obj->btf_module_names)
+		return true;
+
+	for (i = 0; i < obj->nr_btf_module_names; i++) {
+		if (strcmp(obj->btf_module_names[i], name) == 0)
+			return true;
+	}
+
+	pr_debug("skipping module BTF '%s', not in btf_module_names\n", name);
+	return false;
+}
+
+static bool all_needed_module_btfs_loaded(const struct bpf_object *obj)
+{
+	return obj->btf_module_names &&
+	       obj->nr_btf_module_names == obj->btf_module_cnt;
+}
+
 static int load_module_btfs(struct bpf_object *obj)
 {
 	struct bpf_btf_info info;
@@ -5867,6 +5958,11 @@ static int load_module_btfs(struct bpf_object *obj)
 			continue;
 		}
 
+		if (!is_module_btf_needed(obj, name)) {
+			close(fd);
+			continue;
+		}
+
 		btf = btf_get_from_fd(fd, obj->btf_vmlinux);
 		err = libbpf_get_error(btf);
 		if (err) {
@@ -5891,6 +5987,9 @@ static int load_module_btfs(struct bpf_object *obj)
 			break;
 		}
 		obj->btf_module_cnt++;
+
+		if (all_needed_module_btfs_loaded(obj))
+			break;
 	}
 
 	if (err) {
@@ -8508,6 +8607,10 @@ static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf,
 		}
 	}
 
+	err = bpf_object_init_btf_module_names(obj, opts);
+	if (err)
+		goto out;
+
 	err = bpf_object__elf_init(obj);
 	err = err ? : bpf_object__elf_collect(obj);
 	err = err ? : bpf_object__collect_externs(obj);
@@ -9629,6 +9732,8 @@ void bpf_object__close(struct bpf_object *obj)
 		close(obj->jumptable_maps[i].fd);
 	zfree(&obj->jumptable_maps);
 
+	bpf_object_free_btf_module_names(obj);
+
 	free(obj);
 }
 
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index b965ad571540..838602319da8 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -224,10 +224,32 @@ struct bpf_object_open_opts {
 	 * point (/sys/fs/bpf), in case this default behavior is undesirable.
 	 */
 	const char *bpf_token_path;
+	/*
+	 * Optional list of kernel module names whose BTFs should be loaded.
+	 * nr_btf_module_names specifies the number of entries in
+	 * btf_module_names.
+	 *
+	 * If btf_module_names is NULL, all module BTFs are loaded,
+	 * preserving the default behavior. Otherwise, only the BTFs of
+	 * the listed modules are loaded. A non-NULL btf_module_names
+	 * with nr_btf_module_names equal to zero means that no module
+	 * BTFs are loaded.
+	 *
+	 * The list must not contain duplicate entries; otherwise
+	 * -EINVAL is returned.
+	 *
+	 * This affects:
+	 * - BPF CO-RE relocations against types defined in modules;
+	 * - BTF-based resolution of function attach targets for
+	 *   fentry/fexit/fmod_ret/freplace/LSM programs;
+	 * - extern (ksym) resolution for kernel symbols defined in modules.
+	 */
+	const char **btf_module_names;
+	size_t nr_btf_module_names;
 
 	size_t :0;
 };
-#define bpf_object_open_opts__last_field bpf_token_path
+#define bpf_object_open_opts__last_field nr_btf_module_names
 
 /**
  * @brief **bpf_object__open()** creates a bpf_object by opening
-- 
2.34.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH bpf-next v4 2/2] selftests/bpf: add tests for selective module BTF loading
  2026-08-24 12:53 [PATCH bpf-next v4 0/2] libbpf: Improve BPF load performance by selectively loading kmod BTFs Fuyu Zhao
  2026-08-24 12:53 ` [PATCH bpf-next v4 1/2] libbpf: support selective kernel module BTF loading via bpf_object_open_opts Fuyu Zhao
@ 2026-08-24 12:53 ` Fuyu Zhao
  2026-08-24 13:31   ` bot+bpf-ci
  1 sibling, 1 reply; 5+ messages in thread
From: Fuyu Zhao @ 2026-08-24 12:53 UTC (permalink / raw)
  To: bpf, eddyz87, andrii.nakryiko, alan.maguire
  Cc: andrii, ast, daniel, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, shuah, yatsenko, linux-kernel,
	linux-kselftest, Fuyu Zhao

Add selftests covering selective kernel module BTF loading through
bpf_object_open_opts.

The tests verify that loading succeeds when the required module BTF is
requested, fails when only an unrelated module BTF is requested, and
skips loading all module BTFs when an empty module BTF name list is
provided.

Signed-off-by: Fuyu Zhao <zhaofuyu@vivo.com>
---
 .../bpf/prog_tests/btf_module_names.c         | 93 +++++++++++++++++++
 .../selftests/bpf/progs/btf_module_names.c    | 13 +++
 2 files changed, 106 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_module_names.c
 create mode 100644 tools/testing/selftests/bpf/progs/btf_module_names.c

diff --git a/tools/testing/selftests/bpf/prog_tests/btf_module_names.c b/tools/testing/selftests/bpf/prog_tests/btf_module_names.c
new file mode 100644
index 000000000000..d5674cad0017
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/btf_module_names.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+#include "btf_module_names.skel.h"
+
+static void btf_module_names_load(void)
+{
+	struct btf_module_names *skel = NULL;
+	int ret;
+	static const char *mod_names[] = { "bpf_testmod" };
+
+	LIBBPF_OPTS(bpf_object_open_opts, opts,
+		.btf_module_names = mod_names,
+		.nr_btf_module_names = 1,
+	);
+
+	skel = btf_module_names__open_opts(&opts);
+	if (!ASSERT_OK_PTR(skel, "btf_module_names__open_opts"))
+		goto out;
+
+	ret = btf_module_names__load(skel);
+	ASSERT_OK(ret, "btf_module_names__load");
+out:
+	btf_module_names__destroy(skel);
+}
+
+/*
+ * Verify that an unrequested module BTF is skipped. The BPF program
+ * requires the BTF of bpf_testmod, but bpf_testmod is not specified in
+ * btf_module_names, so its BTF is skipped and the BPF program fails to load.
+ */
+static void btf_module_names_skip(void)
+{
+	struct btf_module_names *skel = NULL;
+	int ret;
+	static const char *mod_names[] = { "module_nonexist" };
+
+	LIBBPF_OPTS(bpf_object_open_opts, opts,
+		.btf_module_names = mod_names,
+		.nr_btf_module_names = 1,
+	);
+
+	skel = btf_module_names__open_opts(&opts);
+	if (!ASSERT_OK_PTR(skel, "btf_module_names__open_opts"))
+		goto out;
+
+	ret = btf_module_names__load(skel);
+	ASSERT_ERR(ret, "btf_module_names__load");
+
+out:
+	btf_module_names__destroy(skel);
+}
+
+/*
+ * Verify that an empty filter skips loading all module BTFs. The BPF
+ * program requires bpf_testmod BTF, so it fails to load.
+ */
+static void btf_module_names_empty(void)
+{
+	struct btf_module_names *skel = NULL;
+	int ret;
+	static const char *mod_names[] = { "foo" };
+
+	LIBBPF_OPTS(bpf_object_open_opts, opts,
+		.btf_module_names = mod_names,
+	);
+
+	skel = btf_module_names__open_opts(&opts);
+	if (!ASSERT_OK_PTR(skel, "btf_module_names__open_opts empty"))
+		goto out;
+
+	ret = btf_module_names__load(skel);
+	ASSERT_ERR(ret, "btf_module_names__load empty");
+
+out:
+	btf_module_names__destroy(skel);
+}
+
+void test_btf_module_names(void)
+{
+	if (!env.has_testmod) {
+		test__skip();
+		return;
+	}
+
+	if (test__start_subtest("btf_module_names_load"))
+		btf_module_names_load();
+
+	if (test__start_subtest("btf_module_names_skip"))
+		btf_module_names_skip();
+
+	if (test__start_subtest("btf_module_names_empty"))
+		btf_module_names_empty();
+}
diff --git a/tools/testing/selftests/bpf/progs/btf_module_names.c b/tools/testing/selftests/bpf/progs/btf_module_names.c
new file mode 100644
index 000000000000..232adc0f33f6
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/btf_module_names.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+SEC("fentry/bpf_testmod_loop_test")
+int BPF_PROG(test_btf_module_names)
+{
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.34.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next v4 2/2] selftests/bpf: add tests for selective module BTF loading
  2026-08-24 12:53 ` [PATCH bpf-next v4 2/2] selftests/bpf: add tests for selective module BTF loading Fuyu Zhao
@ 2026-08-24 13:31   ` bot+bpf-ci
  0 siblings, 0 replies; 5+ messages in thread
From: bot+bpf-ci @ 2026-08-24 13:31 UTC (permalink / raw)
  To: zhaofuyu, bpf, eddyz87, andrii.nakryiko, alan.maguire
  Cc: andrii, ast, daniel, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, shuah, yatsenko, linux-kernel,
	linux-kselftest, zhaofuyu, ast, andrii, daniel, martin.lau,
	eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 4445 bytes --]

> diff --git a/tools/testing/selftests/bpf/prog_tests/btf_module_names.c b/tools/testing/selftests/bpf/prog_tests/btf_module_names.c
> new file mode 100644
> index 000000000000..d5674cad0017
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/btf_module_names.c
> @@ -0,0 +1,93 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <test_progs.h>
> +#include "btf_module_names.skel.h"
> +
> +static void btf_module_names_load(void)
> +{
> +	struct btf_module_names *skel = NULL;
> +	int ret;
> +	static const char *mod_names[] = { "bpf_testmod" };
> +
> +	LIBBPF_OPTS(bpf_object_open_opts, opts,
> +		.btf_module_names = mod_names,
> +		.nr_btf_module_names = 1,
> +	);
> +
> +	skel = btf_module_names__open_opts(&opts);
> +	if (!ASSERT_OK_PTR(skel, "btf_module_names__open_opts"))
> +		goto out;
> +
> +	ret = btf_module_names__load(skel);
> +	ASSERT_OK(ret, "btf_module_names__load");

The three subtests (btf_module_names_load, btf_module_names_skip, and
btf_module_names_empty) leave the input-validation paths from the
preceding commit completely unexercised.

That commit adds checks in bpf_object_init_btf_module_names() that are
documented in libbpf.h as part of the API contract, particularly:
"The list must not contain duplicate entries; otherwise -EINVAL is
returned."

Uncovered paths in bpf_object_init_btf_module_names():
- Empty or NULL entry detection (if (!names[i] || !names[i][0]))
- Duplicate name detection (the for loop with strcmp checking all
  previous entries)
- Error cleanup path (err_out:) that calls
  bpf_object_free_btf_module_names() after partial strdup() walk

Would it make sense to add subtests covering these validation paths? A
single extra __open_opts() call checked with ASSERT_ERR_PTR() or
ASSERT_NULL() would exercise each. The duplicate-detection loop is
non-trivial enough to deserve one.

Also, nothing in the series asserts the default btf_module_names == NULL
case (load everything, unchanged behaviour), so a regression that makes
the option mandatory would pass undetected.

> +out:
> +	btf_module_names__destroy(skel);
> +}
> +
> +/*
> + * Verify that an unrequested module BTF is skipped. The BPF program
> + * requires the BTF of bpf_testmod, but bpf_testmod is not specified in
> + * btf_module_names, so its BTF is skipped and the BPF program fails to load.
> + */
> +static void btf_module_names_skip(void)
> +{
> +	struct btf_module_names *skel = NULL;
> +	int ret;
> +	static const char *mod_names[] = { "module_nonexist" };
> +
> +	LIBBPF_OPTS(bpf_object_open_opts, opts,
> +		.btf_module_names = mod_names,
> +		.nr_btf_module_names = 1,
> +	);
> +
> +	skel = btf_module_names__open_opts(&opts);
> +	if (!ASSERT_OK_PTR(skel, "btf_module_names__open_opts"))
> +		goto out;
> +
> +	ret = btf_module_names__load(skel);
> +	ASSERT_ERR(ret, "btf_module_names__load");

A subsystem pattern flags this as potentially concerning: both negative
subtests assert only that the load failed, not the specific reason why.
ASSERT_ERR expands to check ___res < 0, so btf_module_names_skip() and
btf_module_names_empty() pass for any negative return from
btf_module_names__load().

The intended error is specific: with bpf_testmod's BTF filtered out,
find_kernel_btf_id() walks obj->btf_modules and falls through to return
-ESRCH, which bpf_object_load() propagates to __load(). Asserting that
value (for example, ASSERT_EQ(ret, -ESRCH, ...)) would pin the
behaviour.

As written, several unrelated conditions make both subtests report
success while proving nothing about the new filter:

- CONFIG_DEBUG_INFO_BTF_MODULES=n: bpf_testmod loads (so env.has_testmod
  is true and the test is not skipped) but has no BTF at all.
  Attach-target resolution then fails regardless of btf_module_names, so
  both negative subtests pass vacuously.

- Unprivileged/EPERM: load_module_btfs() returns 0 early without loading
  any module BTF (pr_debug skipping message), again yielding -ESRCH from
  an unrelated cause.

- Any future validation of the new opts that rejects the list at load
  time rather than at open time.

Would pinning the expected -ESRCH value make these subtests more robust?

> +
> +out:
> +	btf_module_names__destroy(skel);
> +}

[ ... ]


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/32730521630

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next v4 1/2] libbpf: support selective kernel module BTF loading via bpf_object_open_opts
  2026-08-24 12:53 ` [PATCH bpf-next v4 1/2] libbpf: support selective kernel module BTF loading via bpf_object_open_opts Fuyu Zhao
@ 2026-08-24 13:31   ` bot+bpf-ci
  0 siblings, 0 replies; 5+ messages in thread
From: bot+bpf-ci @ 2026-08-24 13:31 UTC (permalink / raw)
  To: zhaofuyu, bpf, eddyz87, andrii.nakryiko, alan.maguire
  Cc: andrii, ast, daniel, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, shuah, yatsenko, linux-kernel,
	linux-kselftest, zhaofuyu, ast, andrii, daniel, martin.lau,
	eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 2186 bytes --]

> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index b965ad571540..838602319da8 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h

[ ... ]

> @@ -224,10 +224,32 @@ struct bpf_object_open_opts {
>  	 * point (/sys/fs/bpf), in case this default behavior is undesirable.
>  	 */
>  	const char *bpf_token_path;
> +	/*
> +	 * Optional list of kernel module names whose BTFs should be loaded.
> +	 * nr_btf_module_names specifies the number of entries in
> +	 * btf_module_names.
> +	 *
> +	 * If btf_module_names is NULL, all module BTFs are loaded,
> +	 * preserving the default behavior. Otherwise, only the BTFs of
> +	 * the listed modules are loaded. A non-NULL btf_module_names
> +	 * with nr_btf_module_names equal to zero means that no module
> +	 * BTFs are loaded.
> +	 *
> +	 * The list must not contain duplicate entries; otherwise
> +	 * -EINVAL is returned.
> +	 *
> +	 * This affects:
> +	 * - BPF CO-RE relocations against types defined in modules;
> +	 * - BTF-based resolution of function attach targets for
> +	 *   fentry/fexit/fmod_ret/freplace/LSM programs;
> +	 * - extern (ksym) resolution for kernel symbols defined in modules.
                   ^^^^

This isn't a bug, but would it be worth adding struct_ops kernel-type
resolution to the "This affects:" list?

find_struct_ops_kern_types() (tools/lib/bpf/libbpf.c:1049) looks up
'bpf_struct_ops_<name>' via find_ksym_btf_id(), which falls back to
obj->btf_modules[] after load_module_btfs().

A struct_ops implementation whose kernel type lives in a module (e.g. a
module-provided tcp_congestion_ops or sched_ext-style struct_ops) will
therefore stop resolving once a filter that omits that module is supplied.

> +	 */
> +	const char **btf_module_names;
> +	size_t nr_btf_module_names;
>
>  	size_t :0;
>  };
> -#define bpf_object_open_opts__last_field bpf_token_path
> +#define bpf_object_open_opts__last_field nr_btf_module_names



---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/32730521630

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-08-24 13:31 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-24 12:53 [PATCH bpf-next v4 0/2] libbpf: Improve BPF load performance by selectively loading kmod BTFs Fuyu Zhao
2026-08-24 12:53 ` [PATCH bpf-next v4 1/2] libbpf: support selective kernel module BTF loading via bpf_object_open_opts Fuyu Zhao
2026-08-24 13:31   ` bot+bpf-ci
2026-08-24 12:53 ` [PATCH bpf-next v4 2/2] selftests/bpf: add tests for selective module BTF loading Fuyu Zhao
2026-08-24 13:31   ` bot+bpf-ci

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®