Re: [PATCH bpf-next v1 1/4] bpf: Save struct_ops instance pointer in bpf_prog_aux

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jun 24, 2025 at 8:38 AM Andrii Nakryiko
<andrii.nakryiko@xxxxxxxxx> wrote:
>
> On Wed, Jun 18, 2025 at 3:19 PM Amery Hung <ameryhung@xxxxxxxxx> wrote:
> >
> > On Thu, Jun 12, 2025 at 4:08 PM Andrii Nakryiko
> > <andrii.nakryiko@xxxxxxxxx> wrote:
> > >
> > > On Mon, Jun 9, 2025 at 4:27 PM Amery Hung <ameryhung@xxxxxxxxx> wrote:
> > > >
> > > > Allows struct_ops implementors to infer the calling struct_ops instance
> > > > inside a kfunc through prog->aux->this_st_ops. A new field, flags, is
> > > > added to bpf_struct_ops. If BPF_STRUCT_OPS_F_THIS_PTR is set in flags,
> > > > a pointer to the struct_ops structure registered to the kernel (i.e.,
> > > > kvalue->data) will be saved to prog->aux->this_st_ops. To access it in
> > > > a kfunc, use BPF_STRUCT_OPS_F_THIS_PTR with __prog argument [0]. The
> > > > verifier will fixup the argument with a pointer to prog->aux. this_st_ops
> > > > is protected by rcu and is valid until a struct_ops map is unregistered
> > > > updated.
> > > >
> > > > For a struct_ops map with BPF_STRUCT_OPS_F_THIS_PTR, to make sure all
> > > > programs in it have the same this_st_ops, cmpxchg is used. Only if a
> > > > program is not already used in another struct_ops map also with
> > > > BPF_STRUCT_OPS_F_THIS_PTR can it be assigned to the current struct_ops
> > > > map.
> > > >
> > >
> > > Have you considered an alternative to storing this_st_ops in
> > > bpf_prog_aux by setting it at runtime (in struct_ops trampoline) into
> > > bpf_run_ctx (which I think all struct ops programs have set), and then
> > > letting any struct_ops kfunc just access it through current (see other
> > > uses of bpf_run_ctx, if you are unfamiliar). This would avoid all this
> > > business with extra flags and passing bpf_prog_aux as an extra
> > > argument.
> > >
> >
> > I didn't know this. Thanks for suggesting an alternative!
> >
> > > There will be no "only one struct_ops for this BPF program" limitation
> > > either: technically, you could have the same BPF program used from two
> > > struct_ops maps just fine (even at the same time). Then depending on
> > > which struct_ops is currently active, you'd have a corresponding
> > > bpf_run_ctx's struct_ops pointer. It feels like a cleaner approach to
> > > me.
> > >
> >
> > This is a cleaner approach for struct_ops operators. To make it work
> > for kfuncs called in timer callback, I think prog->aux->st_ops is
> > still needed, but at least we can unify how to get this_st_ops in
> > kfunc, in a way that does not requires adding __prog to every kfuncs.
> >
> > +enum bpf_run_ctx_type {
> > +        BPF_CG_RUN_CTX = 0,
> > +        BPF_TRACE_RUN_CTX,
> > +        BPF_TRAMP_RUN_CTX,
> > +        BPF_TIMER_RUN_CTX,
> > +};
> >
> > struct bpf_run_ctx {
> > +        enum bpf_run_ctx_type type;
> > };
> >
> > +struct bpf_timer_run_ctx {
> > +        struct bpf_prog_aux *aux;
> > +};
> >
> > struct bpf_tramp_run_ctx {
> >         ...
> > +        void *st_ops;
> > };
> >
> > In bpf_struct_ops_prepare_trampoline(), the st_ops assignment will be
> > emitted to the trampoline.
> >
> > In bpf_timer_cb(), prepare bpf_timer_run_ctx, where st_ops comes from
> > prog->aux->this_st_ops and set current->bpf_ctx.
> >
> > Finally, in kfuncs that want to know the current struct_ops, call this
> > new function below:
> >
> > +void *bpf_struct_ops_current_st_ops(void)
> > +{
> > +        struct bpf_prog_aux aux;
> > +
> > +        if (!current->bpf_ctx)
> > +                return NULL;
> > +
> > +        switch(current->bpf_ctx->type) {
> > +        case BPF_TRAMP_RUN_CTX:
> > +                return (struct bpf_tramp_run_ctx *)(current->bpf_ctx)->st_ops;
> > +        case BPF_TIMER_RUN_CTX:
> > +                aux = (struct bpf_timer_run_ctx *)(current->bpf_ctx)->aux;
> > +                return rcu_dereference(aux->this_st_ops);
> > +        }
> > +        return NULL;
> > +}
> >
> > What do you think?
>
> I'm not sure I particularly like different ways to get this st_ops
> pointer depending whether we are in an async callback or not. So if
> bpf_prog_aux is inevitable, I'd just stick to that. As far as
> bpf_run_ctx, though, instead of bpf_run_ctx_type, shall we just put
> `struct bpf_prog_aux *` pointer into common struct bpf_run_ctx and
> always set it for all program types that support run_ctx?

No. This is death by a thousand cuts.
bpf trampoline is getting slower and slower.
scx's 'this' case is not a common pattern.





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux