On 8/9/2024 8:51 AM, Amery Hung wrote: > From: Dave Marchevsky <davemarchevsky@xxxxxx> > > Test stashing both referenced kptr and local kptr into local kptrs. Then, > test unstashing them. > > Acked-by: Martin KaFai Lau <martin.lau@xxxxxxxxxx> > Signed-off-by: Dave Marchevsky <davemarchevsky@xxxxxx> > Signed-off-by: Amery Hung <amery.hung@xxxxxxxxxxxxx> Acked-by: Hou Tao <houtao1@xxxxxxxxxx> > --- > .../selftests/bpf/progs/local_kptr_stash.c | 58 ++++++++++++++++++- > 1 file changed, 56 insertions(+), 2 deletions(-) > > diff --git a/tools/testing/selftests/bpf/progs/local_kptr_stash.c b/tools/testing/selftests/bpf/progs/local_kptr_stash.c > index 75043ffc5dad..ce7bf7790917 100644 > --- a/tools/testing/selftests/bpf/progs/local_kptr_stash.c > +++ b/tools/testing/selftests/bpf/progs/local_kptr_stash.c > @@ -8,9 +8,13 @@ > #include "../bpf_experimental.h" > #include "../bpf_testmod/bpf_testmod_kfunc.h" > > +struct plain_local; > + > struct node_data { > long key; > long data; > + struct prog_test_ref_kfunc __kptr *stashed_in_kptr; > + struct plain_local __kptr *stashed_in_local_kptr; > struct bpf_rb_node node; > }; > > @@ -85,18 +89,52 @@ static bool less(struct bpf_rb_node *a, const struct bpf_rb_node *b) > > static int create_and_stash(int idx, int val) > { > + struct prog_test_ref_kfunc *inner_kptr; > + struct plain_local *inner_local_kptr; > struct map_value *mapval; > struct node_data *res; > + unsigned long dummy; > > mapval = bpf_map_lookup_elem(&some_nodes, &idx); > if (!mapval) > return 1; > > + dummy = 0; > + inner_kptr = bpf_kfunc_call_test_acquire(&dummy); > + if (!inner_kptr) > + return 2; > + > + inner_local_kptr = bpf_obj_new(typeof(*inner_local_kptr)); > + if (!inner_local_kptr) { > + bpf_kfunc_call_test_release(inner_kptr); > + return 3; > + } > + > res = bpf_obj_new(typeof(*res)); > - if (!res) > - return 1; > + if (!res) { > + bpf_kfunc_call_test_release(inner_kptr); > + bpf_obj_drop(inner_local_kptr); > + return 4; > + } > res->key = val; > > + inner_kptr = bpf_kptr_xchg(&res->stashed_in_kptr, inner_kptr); > + if (inner_kptr) { > + /* Should never happen, we just obj_new'd res */ > + bpf_kfunc_call_test_release(inner_kptr); > + bpf_obj_drop(inner_local_kptr); > + bpf_obj_drop(res); > + return 5; > + } > + > + inner_local_kptr = bpf_kptr_xchg(&res->stashed_in_local_kptr, inner_local_kptr); > + if (inner_local_kptr) { > + /* Should never happen, we just obj_new'd res */ > + bpf_obj_drop(inner_local_kptr); > + bpf_obj_drop(res); > + return 6; > + } > + > res = bpf_kptr_xchg(&mapval->node, res); > if (res) > bpf_obj_drop(res); > @@ -169,6 +207,8 @@ long stash_local_with_root(void *ctx) > SEC("tc") > long unstash_rb_node(void *ctx) > { > + struct prog_test_ref_kfunc *inner_kptr = NULL; > + struct plain_local *inner_local_kptr = NULL; > struct map_value *mapval; > struct node_data *res; > long retval; > @@ -180,6 +220,20 @@ long unstash_rb_node(void *ctx) > > res = bpf_kptr_xchg(&mapval->node, NULL); > if (res) { > + inner_kptr = bpf_kptr_xchg(&res->stashed_in_kptr, inner_kptr); > + if (!inner_kptr) { > + bpf_obj_drop(res); > + return 1; > + } > + bpf_kfunc_call_test_release(inner_kptr); > + > + inner_local_kptr = bpf_kptr_xchg(&res->stashed_in_local_kptr, inner_local_kptr); > + if (!inner_local_kptr) { > + bpf_obj_drop(res); > + return 1; > + } > + bpf_obj_drop(inner_local_kptr); > + > retval = res->key; > bpf_obj_drop(res); > return retval;