bpf: Add bpf_struct_ops_for_each_prog()

Add a helper that walks the member progs of the struct_ops map
containing a given @kdata vmtable. struct_ops ->reg() callbacks (and
similar) sometimes need to inspect the loaded BPF programs, e.g. to
discover maps they reference via prog->aux->used_maps.

The implementation mirrors bpf_struct_ops_id(): container_of @kdata
to recover the bpf_struct_ops_map, then iterate st_map->links[i]->prog
for i in [0, funcs_cnt). Same access pattern, no new locking - by the
time ->reg() fires st_map is fully populated and stable.

A sched_ext follow-up walks the member progs of a cid-form scheduler's
struct_ops map, reads prog->aux->arena directly, and requires all member
progs to reference exactly one arena, without requiring the BPF program
to call a registration kfunc.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Link: https://lore.kernel.org/r/20260522172219.1423324-5-tj@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Tejun Heo 2026-05-22 07:22:15 -10:00 committed by Alexei Starovoitov
parent f211c81ddc
commit 7c48a28c1b
2 changed files with 39 additions and 0 deletions

View File

@ -2131,6 +2131,9 @@ int bpf_prog_assoc_struct_ops(struct bpf_prog *prog, struct bpf_map *map);
void bpf_prog_disassoc_struct_ops(struct bpf_prog *prog);
void *bpf_prog_get_assoc_struct_ops(const struct bpf_prog_aux *aux);
u32 bpf_struct_ops_id(const void *kdata);
int bpf_struct_ops_for_each_prog(const void *kdata,
int (*cb)(struct bpf_prog *prog, void *data),
void *data);
#ifdef CONFIG_NET
/* Define it here to avoid the use of forward declaration */

View File

@ -1204,6 +1204,42 @@ u32 bpf_struct_ops_id(const void *kdata)
}
EXPORT_SYMBOL_GPL(bpf_struct_ops_id);
/**
* bpf_struct_ops_for_each_prog - Invoke @cb for each member prog
* @kdata: kernel-side struct_ops vmtable (the @kdata arg to ->reg/->update/->unreg)
* @cb: callback invoked once per member prog; non-zero return stops iteration
* @data: opaque argument passed to @cb
*
* Walks the struct_ops member progs registered on the map containing @kdata.
* Intended for use from struct_ops ->reg() callbacks (and similar) that need to
* inspect the loaded BPF programs (for example to discover maps they reference
* via @prog->aux->used_maps).
*
* Return 0 if iteration completed, otherwise the first non-zero @cb return.
*/
int bpf_struct_ops_for_each_prog(const void *kdata,
int (*cb)(struct bpf_prog *prog, void *data),
void *data)
{
struct bpf_struct_ops_value *kvalue;
struct bpf_struct_ops_map *st_map;
u32 i;
int ret;
kvalue = container_of(kdata, struct bpf_struct_ops_value, data);
st_map = container_of(kvalue, struct bpf_struct_ops_map, kvalue);
for (i = 0; i < st_map->funcs_cnt; i++) {
if (!st_map->links[i])
continue;
ret = cb(st_map->links[i]->prog, data);
if (ret)
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(bpf_struct_ops_for_each_prog);
static bool bpf_struct_ops_valid_to_reg(struct bpf_map *map)
{
struct bpf_struct_ops_map *st_map = (struct bpf_struct_ops_map *)map;