On Thu, Apr 28, 2022 at 6:52 PM Kui-Feng Lee <kuifeng@xxxxxx> wrote: > > On Wed, 2022-04-20 at 10:37 -0700, Andrii Nakryiko wrote: > > On Fri, Apr 15, 2022 at 9:30 PM Kui-Feng Lee <kuifeng@xxxxxx> wrote: > > > > > > Replace struct bpf_tramp_progs with struct bpf_tramp_links to > > > collect > > > struct bpf_tramp_link(s) for a trampoline. struct bpf_tramp_link > > > extends bpf_link to act as a linked list node. > > > > > > arch_prepare_bpf_trampoline() accepts a struct bpf_tramp_links to > > > collects all bpf_tramp_link(s) that a trampoline should call. > > > > > > Change BPF trampoline and bpf_struct_ops to pass bpf_tramp_links > > > instead of bpf_tramp_progs. > > > > > > Signed-off-by: Kui-Feng Lee <kuifeng@xxxxxx> > > > --- > > > arch/x86/net/bpf_jit_comp.c | 36 +++++++++-------- > > > include/linux/bpf.h | 36 +++++++++++------ > > > include/linux/bpf_types.h | 1 + > > > include/uapi/linux/bpf.h | 1 + > > > kernel/bpf/bpf_struct_ops.c | 69 ++++++++++++++++++++++-------- > > > -- > > > kernel/bpf/syscall.c | 23 ++++------- > > > kernel/bpf/trampoline.c | 73 +++++++++++++++++++----------- > > > ---- > > > net/bpf/bpf_dummy_struct_ops.c | 37 ++++++++++++++--- > > > tools/bpf/bpftool/link.c | 1 + > > > tools/include/uapi/linux/bpf.h | 1 + > > > 10 files changed, 175 insertions(+), 103 deletions(-) > > > > > > > [...] > > > > > @@ -385,6 +399,7 @@ static int > > > bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, > > > for_each_member(i, t, member) { > > > const struct btf_type *mtype, *ptype; > > > struct bpf_prog *prog; > > > + struct bpf_tramp_link *link; > > > u32 moff; > > > > > > moff = __btf_member_bit_offset(t, member) / 8; > > > @@ -438,16 +453,26 @@ static int > > > bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, > > > err = PTR_ERR(prog); > > > goto reset_unlock; > > > } > > > - st_map->progs[i] = prog; > > > > > > if (prog->type != BPF_PROG_TYPE_STRUCT_OPS || > > > prog->aux->attach_btf_id != st_ops->type_id || > > > prog->expected_attach_type != i) { > > > + bpf_prog_put(prog); > > > err = -EINVAL; > > > goto reset_unlock; > > > } > > > > > > - err = bpf_struct_ops_prepare_trampoline(tprogs, > > > prog, > > > + link = kzalloc(sizeof(*link), GFP_USER); > > > > seems like you are leaking this link and all the links allocated in > > previous successful iterations of this loop? > > > > > + if (!link) { > > > + bpf_prog_put(prog); > > > + err = -ENOMEM; > > > + goto reset_unlock; > > > + } > > > + bpf_link_init(&link->link, > > > BPF_LINK_TYPE_STRUCT_OPS, > > > + &bpf_struct_ops_link_lops, prog); > > > + st_map->links[i] = &link->link; > > > + > > > + err = bpf_struct_ops_prepare_trampoline(tlinks, > > > link, > > > &st_ops- > > > >func_models[i], > > > image, > > > image_end); > > > if (err < 0) > > > @@ -490,7 +515,7 @@ static int > > > bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key, > > > memset(uvalue, 0, map->value_size); > > > memset(kvalue, 0, map->value_size); > > > unlock: > > > - kfree(tprogs); > > > + kfree(tlinks); > > > > so you'll need to free those links inside tlinks (or wherever else > > they are stored) > > > > > mutex_unlock(&st_map->lock); > > > return err; > > > } > > > @@ -545,9 +570,9 @@ static void bpf_struct_ops_map_free(struct > > > bpf_map *map) > > > { > > > struct bpf_struct_ops_map *st_map = (struct > > > bpf_struct_ops_map *)map; > > > > > > - if (st_map->progs) > > > + if (st_map->links) > > > bpf_struct_ops_map_put_progs(st_map); > > > - bpf_map_area_free(st_map->progs); > > > + bpf_map_area_free(st_map->links); > > > bpf_jit_free_exec(st_map->image); > > > bpf_map_area_free(st_map->uvalue); > > > bpf_map_area_free(st_map); > > > > [...] > > > > > @@ -105,10 +120,20 @@ int bpf_struct_ops_test_run(struct bpf_prog > > > *prog, const union bpf_attr *kattr, > > > } > > > set_vm_flush_reset_perms(image); > > > > > > + link = kzalloc(sizeof(*link), GFP_USER); > > > + if (!link) { > > > + err = -ENOMEM; > > > + goto out; > > > + } > > > + /* prog doesn't take the ownership of the reference from > > > caller */ > > > + bpf_prog_inc(prog); > > > + bpf_link_init(&link->link, BPF_LINK_TYPE_STRUCT_OPS, > > > &bpf_struct_ops_link_lops, prog); > > > + > > > op_idx = prog->expected_attach_type; > > > - err = bpf_struct_ops_prepare_trampoline(tprogs, prog, > > > + err = bpf_struct_ops_prepare_trampoline(tlinks, link, > > > &st_ops- > > > >func_models[op_idx], > > > image, image + > > > PAGE_SIZE); > > > + > > > > nit: no need for extra empty line here > > > > > if (err < 0) > > > goto out; > > > > > > @@ -124,7 +149,9 @@ int bpf_struct_ops_test_run(struct bpf_prog > > > *prog, const union bpf_attr *kattr, > > > out: > > > kfree(args); > > > bpf_jit_free_exec(image); > > > - kfree(tprogs); > > > + if (link) > > > + bpf_link_put(&link->link); > > > > you never to bpf_link_prime() and bpf_link_settle() for these "pseudo > > links" for struct_ops, so there is no need for bpf_link_put(), it can > > be just bpf_link_free(), right? > > Just realize that bpf_link_free() is a static function of > bpf/syscall.c. And, this code is for testing only. So, I don't touch > this line. > we can make it non-static and expose along with other generic bpf_link internal APIs, like bpf_link_cleanup() > > > > > + kfree(tlinks); > > > return err; > > > } > > > > > > diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c > > > index 8fb0116f9136..6353a789322b 100644 > > > --- a/tools/bpf/bpftool/link.c > > > +++ b/tools/bpf/bpftool/link.c > > > @@ -23,6 +23,7 @@ static const char * const link_type_name[] = { > > > [BPF_LINK_TYPE_XDP] = "xdp", > > > [BPF_LINK_TYPE_PERF_EVENT] = "perf_event", > > > [BPF_LINK_TYPE_KPROBE_MULTI] = "kprobe_multi", > > > + [BPF_LINK_TYPE_STRUCT_OPS] = "struct_ops", > > > }; > > > > > > static struct hashmap *link_table; > > > diff --git a/tools/include/uapi/linux/bpf.h > > > b/tools/include/uapi/linux/bpf.h > > > index d14b10b85e51..a4f557338af7 100644 > > > --- a/tools/include/uapi/linux/bpf.h > > > +++ b/tools/include/uapi/linux/bpf.h > > > @@ -1013,6 +1013,7 @@ enum bpf_link_type { > > > BPF_LINK_TYPE_XDP = 6, > > > BPF_LINK_TYPE_PERF_EVENT = 7, > > > BPF_LINK_TYPE_KPROBE_MULTI = 8, > > > + BPF_LINK_TYPE_STRUCT_OPS = 9, > > > > > > MAX_BPF_LINK_TYPE, > > > }; > > > -- > > > 2.30.2 > > > >