On Tue, Jun 3, 2025 at 2:09 PM Song Liu <song@xxxxxxxxxx> wrote: > > On Tue, Jun 3, 2025 at 11:40 AM Andrii Nakryiko > <andrii.nakryiko@xxxxxxxxx> wrote: > [...] > > > +__bpf_kfunc struct path *bpf_iter_path_next(struct bpf_iter_path *it) > > > +{ > > > + struct bpf_iter_path_kern *kit = (void *)it; > > > + struct path root = {}; > > > + > > > + if (!path_walk_parent(&kit->path, &root)) > > > + return NULL; > > > + return &kit->path; > > > +} > > > + > > > +__bpf_kfunc void bpf_iter_path_destroy(struct bpf_iter_path *it) > > > +{ > > > + struct bpf_iter_path_kern *kit = (void *)it; > > > + > > > + path_put(&kit->path); > > > > note, destroy() will be called even if construction of iterator fails > > or we exhausted iterator. So you need to make sure that you have > > bpf_iter_path state where you can detect that there is no path present > > and skip path_put(). > > In bpf_iter_path_next(), when path_walk_parent() returns false, we > still hold reference to kit->path, then _destroy() will release it. So we > should be fine, no? you still need to handle iterators that failed to be initialized, though? And one can argue that if path_walk_parent() returns false, we need to put that last path before returning NULL, no? > > Thanks, > Song > > > > > > +} > > > + > > > +__bpf_kfunc_end_defs(); > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > > index a7d6e0c5928b..45b45cdfb223 100644 > > > --- a/kernel/bpf/verifier.c > > > +++ b/kernel/bpf/verifier.c > > > @@ -7036,6 +7036,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket) { > > > struct sock *sk; > > > }; > > > > > > +BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct path) { > > > + struct dentry *dentry; > > > +}; > > > + > > > static bool type_is_rcu(struct bpf_verifier_env *env, > > > struct bpf_reg_state *reg, > > > const char *field_name, u32 btf_id) > > > @@ -7076,6 +7080,7 @@ static bool type_is_trusted_or_null(struct bpf_verifier_env *env, > > > const char *field_name, u32 btf_id) > > > { > > > BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket)); > > > + BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct path)); > > > > > > return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, > > > "__safe_trusted_or_null"); > > > -- > > > 2.47.1 > > > > >