> > > +BTF_KFUNCS_START(stream_consumer_kfunc_set) > > > +BTF_ID_FLAGS(func, bpf_stream_next_elem_batch, KF_ACQUIRE | KF_RET_NULL | KF_TRUSTED_ARGS) > > > +BTF_ID_FLAGS(func, bpf_stream_free_elem_batch, KF_RELEASE) > > > +BTF_ID_FLAGS(func, bpf_stream_next_elem, KF_ACQUIRE | KF_RET_NULL | KF_TRUSTED_ARGS) > > > +BTF_ID_FLAGS(func, bpf_stream_free_elem, KF_RELEASE) > > > +BTF_ID_FLAGS(func, bpf_prog_stream_get, KF_ACQUIRE | KF_RET_NULL) > > > +BTF_ID_FLAGS(func, bpf_prog_stream_put, KF_RELEASE) > > > +BTF_KFUNCS_END(stream_consumer_kfunc_set) > > > > This is a complicated API. > > If we anticipate that users intend to write this info to ring buffers > > maybe just provide a function doing that and do not expose complete API? > > I don't think anyone will use these functions directly, though they > can if they want to. > It's meant to be hidden behind bpftool, and macros to print stuff like > bpf_printk(). I have to agree with Eduard here. The api feels overdesigned. I don't see how it can be reused anywhere outside of bpftool. Instead of introducing mem_slice concept and above kfuncs, let's have one special kfunc that will take prog_id, stream_id and will move things into dynptr returning EAGAIN/ENOENT when necessary. EFAULT shouldn't be possible when the whole SEC("syscall") int bpftool_dump_prog_stream(void *ctx) {..} will be one kfunc. bpf_stream_dtor_ids won't be needed either. Hard coding such a big logic into one kfunc is not pretty, and smaller kfuncs/building blocks would be preferred any day, but these stream_consumer_kfunc_set just don't look reusable.