* [PATCH bpf-next 0/3] libbpf: Follow-ups to BPF program manual loading
@ 2026-11-01 19:54 Andrey Grodzovsky
2026-11-01 19:54 ` [PATCH bpf-next 1/3] selftests/bpf: Convert veristat to BPF_PROG_LOAD_STRATEGY_MANUAL Andrey Grodzovsky
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Andrey Grodzovsky @ 2026-11-01 19:54 UTC (permalink / raw)
To: bpf; +Cc: andrii, martin.kelly, slava.imameev
This is a follow-up to the libbpf BPF program manual loading series [1].
It addresses a few review comments made in that series.
- Patches 1-2: Split the veristat conversion work into two separate
patches, one for the actual conversion and another for the arena
selftest update.
- Patch 3: Small libbpf cleanups in the manual loading code, and
documentation of when bpf_program__set_autoload() and
bpf_program__set_load_strategy() fail.
[1] https://lore.kernel.org/bpf/20261029223348.3730738-1-andrey.grodzovsky@crowdstrike.com/
Andrey Grodzovsky (3):
selftests/bpf: Convert veristat to BPF_PROG_LOAD_STRATEGY_MANUAL
selftests/bpf: Test arena autobind with BPF_PROG_LOAD_STRATEGY_MANUAL
libbpf: Clean up BPF program manual loading
tools/lib/bpf/libbpf.c | 15 +++---
tools/lib/bpf/libbpf.h | 14 +++++-
.../bpf/prog_tests/test_struct_ops_arena.c | 48 +++++++++++++++++--
tools/testing/selftests/bpf/veristat.c | 20 ++++----
4 files changed, 72 insertions(+), 25 deletions(-)
base-commit: eaae576c34d7e001767b6845a5950b0b8db3e68a
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH bpf-next 1/3] selftests/bpf: Convert veristat to BPF_PROG_LOAD_STRATEGY_MANUAL
2026-11-01 19:54 [PATCH bpf-next 0/3] libbpf: Follow-ups to BPF program manual loading Andrey Grodzovsky
@ 2026-11-01 19:54 ` Andrey Grodzovsky
2026-11-01 19:54 ` [PATCH bpf-next 2/3] selftests/bpf: Test arena autobind with BPF_PROG_LOAD_STRATEGY_MANUAL Andrey Grodzovsky
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Andrey Grodzovsky @ 2026-11-01 19:54 UTC (permalink / raw)
To: bpf; +Cc: andrii, martin.kelly, slava.imameev
veristat used bpf_program__clone() to verify each program in
isolation. Replace it with BPF_PROG_LOAD_STRATEGY_MANUAL plus
bpf_program__load()/bpf_program__unload().
Unlike clone(), which skips binding RODATA maps to avoid mutating
shared object state, bpf_program__load() does bind them - but each
program is unloaded right after verification, dropping the binding
along with it.
Suggested-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
---
tools/testing/selftests/bpf/veristat.c | 20 ++++++++------------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/tools/testing/selftests/bpf/veristat.c b/tools/testing/selftests/bpf/veristat.c
index 9cfc9b4b41c1..0cd19b59037f 100644
--- a/tools/testing/selftests/bpf/veristat.c
+++ b/tools/testing/selftests/bpf/veristat.c
@@ -1678,7 +1678,6 @@ static int process_prog(const char *filename, struct bpf_object *obj, struct bpf
const char *base_filename = basename(strdupa(filename));
const char *prog_name = bpf_program__name(prog);
long mem_peak_a, mem_peak_b, mem_peak = -1;
- LIBBPF_OPTS(bpf_prog_load_opts, opts);
char *buf;
int buf_sz, log_level;
struct verif_stats *stats;
@@ -1726,18 +1725,15 @@ static int process_prog(const char *filename, struct bpf_object *obj, struct bpf
if (env.force_reg_invariants)
bpf_program__add_flags(prog, BPF_F_TEST_REG_INVARIANTS);
- opts.log_buf = buf;
- opts.log_size = buf_sz;
- opts.log_level = log_level;
+ bpf_program__set_log_buf(prog, buf, buf_sz);
+ bpf_program__set_log_level(prog, log_level);
cgroup_err = reset_stat_cgroup();
mem_peak_a = cgroup_memory_peak();
- fd = bpf_program__clone(prog, &opts);
- if (fd < 0) {
- err = fd;
- if (env.verbose)
- fprintf(stderr, "Failed to load program %s %d\n", prog_name, err);
- }
+ err = bpf_program__load(prog);
+ fd = err == 0 ? bpf_program__fd(prog) : -1;
+ if (err && env.verbose)
+ fprintf(stderr, "Failed to load program %s %d\n", prog_name, err);
mem_peak_b = cgroup_memory_peak();
if (!cgroup_err && mem_peak_a >= 0 && mem_peak_b >= 0)
mem_peak = mem_peak_b - mem_peak_a;
@@ -1774,7 +1770,7 @@ static int process_prog(const char *filename, struct bpf_object *obj, struct bpf
if (verif_log_buf != buf)
free(buf);
if (fd > 0)
- close(fd);
+ bpf_program__unload(prog);
return 0;
}
@@ -2297,7 +2293,7 @@ static int process_obj(const char *filename)
env.files_processed++;
bpf_object__for_each_program(prog, obj) {
- bpf_program__set_autoload(prog, true);
+ bpf_program__set_load_strategy(prog, BPF_PROG_LOAD_STRATEGY_MANUAL);
prog_cnt++;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH bpf-next 2/3] selftests/bpf: Test arena autobind with BPF_PROG_LOAD_STRATEGY_MANUAL
2026-11-01 19:54 [PATCH bpf-next 0/3] libbpf: Follow-ups to BPF program manual loading Andrey Grodzovsky
2026-11-01 19:54 ` [PATCH bpf-next 1/3] selftests/bpf: Convert veristat to BPF_PROG_LOAD_STRATEGY_MANUAL Andrey Grodzovsky
@ 2026-11-01 19:54 ` Andrey Grodzovsky
2026-11-01 19:54 ` [PATCH bpf-next 3/3] libbpf: Clean up BPF program manual loading Andrey Grodzovsky
2026-11-05 22:30 ` [PATCH bpf-next 0/3] libbpf: Follow-ups to " patchwork-bot+netdevbpf
3 siblings, 0 replies; 5+ messages in thread
From: Andrey Grodzovsky @ 2026-11-01 19:54 UTC (permalink / raw)
To: bpf; +Cc: andrii, martin.kelly, slava.imameev
Add an arena_autobind_manual subtest to struct_ops_arena. It marks every
program of struct_ops_arena_autobind as MANUAL, prepares the object, then
loads each program with bpf_program__load() and checks that it is bound to
the arena before unloading it. This is the same check
arena_autobind_clone does for bpf_program__clone().
Also reword the arena_autobind_clone() comment, which no longer refers to
veristat.
Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
---
.../bpf/prog_tests/test_struct_ops_arena.c | 48 +++++++++++++++++--
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/test_struct_ops_arena.c b/tools/testing/selftests/bpf/prog_tests/test_struct_ops_arena.c
index e7580b9f0fc2..a8bd10bab5dd 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_struct_ops_arena.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_struct_ops_arena.c
@@ -192,9 +192,9 @@ static void arena_autobind(void)
}
/*
- * The same binding through bpf_object__prepare() and bpf_program__clone(), the
- * way veristat loads a program: the arena takes slot 0 of a continuous
- * fd_array, next to the module BTF of the kfunc the trigger calls.
+ * The same binding through bpf_object__prepare() and bpf_program__clone(),
+ * the arena takes slot 0 of a continuous fd_array, next to the module BTF
+ * of the kfunc the trigger calls.
*/
static void arena_autobind_clone(void)
{
@@ -225,6 +225,46 @@ static void arena_autobind_clone(void)
struct_ops_arena_autobind__destroy(skel);
}
+/*
+ * The same binding through BPF_PROG_LOAD_STRATEGY_MANUAL: every program is
+ * loaded with bpf_program__load() after bpf_object__prepare() and unloaded
+ * again, the way veristat loads programs.
+ */
+static void arena_autobind_manual(void)
+{
+ struct struct_ops_arena_autobind *skel;
+ struct bpf_map_info info = {};
+ __u32 len = sizeof(info);
+ struct bpf_program *prog;
+ int err;
+
+ skel = struct_ops_arena_autobind__open();
+ if (!ASSERT_OK_PTR(skel, "struct_ops_arena_autobind__open"))
+ return;
+
+ bpf_object__for_each_program(prog, skel->obj) {
+ err = bpf_program__set_load_strategy(prog, BPF_PROG_LOAD_STRATEGY_MANUAL);
+ if (!ASSERT_OK(err, "set_load_strategy"))
+ goto out;
+ }
+ err = bpf_object__prepare(skel->obj);
+ if (!ASSERT_OK(err, "prepare"))
+ goto out;
+ err = bpf_map_get_info_by_fd(bpf_map__fd(skel->maps.arena), &info, &len);
+ if (!ASSERT_OK(err, "arena_info"))
+ goto out;
+ bpf_object__for_each_program(prog, skel->obj) {
+ err = bpf_program__load(prog);
+ if (!ASSERT_OK(err, bpf_program__name(prog)))
+ continue;
+ assert_prog_map(bpf_program__fd(prog), info.id, bpf_program__name(prog));
+ bpf_program__unload(prog);
+ ASSERT_LT(bpf_program__fd(prog), 0, "unloaded");
+ }
+out:
+ struct_ops_arena_autobind__destroy(skel);
+}
+
/*
* An arena exclusive to a program is bound to that program all the same: the
* kernel checks an exclusive map against the digest of the final program, so
@@ -315,6 +355,8 @@ void serial_test_struct_ops_arena(void)
arena_autobind();
if (test__start_subtest("arena_autobind_clone"))
arena_autobind_clone();
+ if (test__start_subtest("arena_autobind_manual"))
+ arena_autobind_manual();
if (test__start_subtest("arena_autobind_excl"))
arena_autobind_excl();
#else
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH bpf-next 3/3] libbpf: Clean up BPF program manual loading
2026-11-01 19:54 [PATCH bpf-next 0/3] libbpf: Follow-ups to BPF program manual loading Andrey Grodzovsky
2026-11-01 19:54 ` [PATCH bpf-next 1/3] selftests/bpf: Convert veristat to BPF_PROG_LOAD_STRATEGY_MANUAL Andrey Grodzovsky
2026-11-01 19:54 ` [PATCH bpf-next 2/3] selftests/bpf: Test arena autobind with BPF_PROG_LOAD_STRATEGY_MANUAL Andrey Grodzovsky
@ 2026-11-01 19:54 ` Andrey Grodzovsky
2026-11-05 22:30 ` [PATCH bpf-next 0/3] libbpf: Follow-ups to " patchwork-bot+netdevbpf
3 siblings, 0 replies; 5+ messages in thread
From: Andrey Grodzovsky @ 2026-11-01 19:54 UTC (permalink / raw)
To: bpf; +Cc: andrii, martin.kelly, slava.imameev
Follow-up cleanups to the manual loading series, just
some extra documentation to the API headers, reject
subprograms in bpf_program__set_load_strategy() for every
strategy and a few more NITs.
Suggested-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Andrey Grodzovsky <andrey.grodzovsky@crowdstrike.com>
---
tools/lib/bpf/libbpf.c | 15 ++++++---------
tools/lib/bpf/libbpf.h | 14 +++++++++++++-
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 02e75b183ed0..446b947c48f3 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -9844,7 +9844,7 @@ static int bpf_object_load(struct bpf_object *obj, int extra_log_level, const ch
err = bpf_gen__finish(obj->gen_loader, obj->nr_programs, obj->nr_maps);
}
- bpf_object_post_load_cleanup(obj, false);
+ bpf_object_post_load_cleanup(obj, false /* !force */);
obj->state = OBJ_LOADED; /* doesn't matter if successfully or not */
if (err) {
@@ -16013,16 +16013,14 @@ int bpf_program__set_load_strategy(struct bpf_program *prog, enum bpf_prog_load_
if (obj->state >= OBJ_PREPARED)
return libbpf_err(-EINVAL);
+ if (prog_is_subprog(obj, prog))
+ return libbpf_err(-EINVAL);
+
switch (strategy) {
case BPF_PROG_LOAD_STRATEGY_DISABLED:
case BPF_PROG_LOAD_STRATEGY_AUTO:
- prog->load_strategy = strategy;
- break;
case BPF_PROG_LOAD_STRATEGY_MANUAL:
- if (prog_is_subprog(obj, prog))
- return libbpf_err(-EINVAL);
-
- prog->load_strategy = BPF_PROG_LOAD_STRATEGY_MANUAL;
+ prog->load_strategy = strategy;
break;
default:
return libbpf_err(-EINVAL);
@@ -16036,8 +16034,7 @@ enum bpf_prog_load_strategy bpf_program__load_strategy(const struct bpf_program
return prog->load_strategy;
}
-int
-bpf_program__load(struct bpf_program *prog)
+int bpf_program__load(struct bpf_program *prog)
{
int err;
struct bpf_object *obj = prog->obj;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 22204a544b23..a8a23c135c17 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -390,6 +390,17 @@ LIBBPF_API void bpf_program__set_ifindex(struct bpf_program *prog,
LIBBPF_API const char *bpf_program__name(const struct bpf_program *prog);
LIBBPF_API const char *bpf_program__section_name(const struct bpf_program *prog);
LIBBPF_API bool bpf_program__autoload(const struct bpf_program *prog);
+
+/**
+ * @brief **bpf_program__set_autoload()** sets whether a BPF program is
+ * loaded automatically when its bpf_object is loaded.
+ *
+ * @param prog BPF program to update
+ * @param autoload true to load the program automatically, false to disable
+ * its loading
+ * @return 0 on success; -EINVAL if the object was already prepared or if the
+ * program is a subprogram
+ */
LIBBPF_API int bpf_program__set_autoload(struct bpf_program *prog, bool autoload);
LIBBPF_API bool bpf_program__autoattach(const struct bpf_program *prog);
LIBBPF_API void bpf_program__set_autoattach(struct bpf_program *prog, bool autoattach);
@@ -2177,7 +2188,8 @@ enum bpf_prog_load_strategy {
*
* @param prog BPF program to update
* @param strategy new load strategy for the program
- * @return 0 on success; negative error code if the object was already prepared
+ * @return 0 on success; -EINVAL if the object was already prepared, if the
+ * strategy is not a valid one, or if the program is a subprogram
*/
LIBBPF_API int bpf_program__set_load_strategy(struct bpf_program *prog,
enum bpf_prog_load_strategy strategy);
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH bpf-next 0/3] libbpf: Follow-ups to BPF program manual loading
2026-11-01 19:54 [PATCH bpf-next 0/3] libbpf: Follow-ups to BPF program manual loading Andrey Grodzovsky
` (2 preceding siblings ...)
2026-11-01 19:54 ` [PATCH bpf-next 3/3] libbpf: Clean up BPF program manual loading Andrey Grodzovsky
@ 2026-11-05 22:30 ` patchwork-bot+netdevbpf
3 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-11-05 22:30 UTC (permalink / raw)
To: Andrey Grodzovsky; +Cc: bpf, andrii, martin.kelly, slava.imameev
Hello:
This series was applied to bpf/bpf-next.git (master)
by Andrii Nakryiko <andrii@kernel.org>:
On Sun, 1 Nov 2026 14:54:50 -0500 you wrote:
> This is a follow-up to the libbpf BPF program manual loading series [1].
> It addresses a few review comments made in that series.
>
> - Patches 1-2: Split the veristat conversion work into two separate
> patches, one for the actual conversion and another for the arena
> selftest update.
> - Patch 3: Small libbpf cleanups in the manual loading code, and
> documentation of when bpf_program__set_autoload() and
> bpf_program__set_load_strategy() fail.
>
> [...]
Here is the summary with links:
- [bpf-next,1/3] selftests/bpf: Convert veristat to BPF_PROG_LOAD_STRATEGY_MANUAL
https://git.kernel.org/bpf/bpf-next/c/594389488d70
- [bpf-next,2/3] selftests/bpf: Test arena autobind with BPF_PROG_LOAD_STRATEGY_MANUAL
https://git.kernel.org/bpf/bpf-next/c/cc22c1bc89b9
- [bpf-next,3/3] libbpf: Clean up BPF program manual loading
https://git.kernel.org/bpf/bpf-next/c/87ace1169ed7
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-05 22:30 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-01 19:54 [PATCH bpf-next 0/3] libbpf: Follow-ups to BPF program manual loading Andrey Grodzovsky
2026-11-01 19:54 ` [PATCH bpf-next 1/3] selftests/bpf: Convert veristat to BPF_PROG_LOAD_STRATEGY_MANUAL Andrey Grodzovsky
2026-11-01 19:54 ` [PATCH bpf-next 2/3] selftests/bpf: Test arena autobind with BPF_PROG_LOAD_STRATEGY_MANUAL Andrey Grodzovsky
2026-11-01 19:54 ` [PATCH bpf-next 3/3] libbpf: Clean up BPF program manual loading Andrey Grodzovsky
2026-11-05 22:30 ` [PATCH bpf-next 0/3] libbpf: Follow-ups to " patchwork-bot+netdevbpf
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.