linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ming Lei <tom.leiming@gmail.com>
To: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: Martin KaFai Lau <martin.lau@kernel.org>,
	Amery Hung <ameryhung@gmail.com>, Jens Axboe <axboe@kernel.dk>,
	linux-block@vger.kernel.org, bpf <bpf@vger.kernel.org>,
	Alexei Starovoitov <ast@kernel.org>,
	Martin KaFai Lau <martin.lau@linux.dev>,
	Yonghong Song <yonghong.song@linux.dev>
Subject: Re: [RFC PATCH 08/22] ublk: bpf: add bpf struct_ops
Date: Wed, 15 Jan 2025 19:58:27 +0800	[thread overview]
Message-ID: <Z4ei40AVuX2sCTmE@fedora> (raw)
In-Reply-To: <CAADnVQK1y2A_-Co5Jx=eeusbcMbEgErxuPzgCqA0yvUU6Uw1CA@mail.gmail.com>

Hello Alexei,

On Mon, Jan 13, 2025 at 01:30:45PM -0800, Alexei Starovoitov wrote:
> On Sun, Jan 12, 2025 at 8:08 PM Ming Lei <tom.leiming@gmail.com> wrote:
> >
> > Hello Alexei,
> >
> > Thanks for your comments!
> >
> > On Thu, Jan 09, 2025 at 05:43:12PM -0800, Alexei Starovoitov wrote:
> > > On Tue, Jan 7, 2025 at 4:08 AM Ming Lei <tom.leiming@gmail.com> wrote:
> > > > +
> > > > +/* Return true if io cmd is queued, otherwise forward it to userspace */
> > > > +bool ublk_run_bpf_handler(struct ublk_queue *ubq, struct request *req,
> > > > +                         queue_io_cmd_t cb)
> > > > +{
> > > > +       ublk_bpf_return_t ret;
> > > > +       struct ublk_rq_data *data = blk_mq_rq_to_pdu(req);
> > > > +       struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
> > > > +       struct ublk_bpf_io *bpf_io = &data->bpf_data;
> > > > +       const unsigned long total = iod->nr_sectors << 9;
> > > > +       unsigned int done = 0;
> > > > +       bool res = true;
> > > > +       int err;
> > > > +
> > > > +       if (!test_bit(UBLK_BPF_IO_PREP, &bpf_io->flags))
> > > > +               ublk_bpf_prep_io(bpf_io, iod);
> > > > +
> > > > +       do {
> > > > +               enum ublk_bpf_disposition rc;
> > > > +               unsigned int bytes;
> > > > +
> > > > +               ret = cb(bpf_io, done);
> > >
> > > High level observation...
> > > I suspect forcing all sturct_ops callbacks to have only these
> > > two arguments and packing args into ublk_bpf_io
> > > will be limiting in the long term.
> >
> > There are three callbacks defined, and only the two with same type for
> > queuing io commands are covered in this function.
> >
> > But yes, callback type belongs to API, which should be designed
> > carefully, and I will think about further.
> >
> > >
> > > And this part of api would need to be redesigned,
> > > but since it's not an uapi... not a big deal.
> > >
> > > > +               rc = ublk_bpf_get_disposition(ret);
> > > > +
> > > > +               if (rc == UBLK_BPF_IO_QUEUED)
> > > > +                       goto exit;
> > > > +
> > > > +               if (rc == UBLK_BPF_IO_REDIRECT)
> > > > +                       break;
> > >
> > > Same point about return value processing...
> > > Each struct_ops callback could have had its own meaning
> > > of retvals.
> > > I suspect it would have been more flexible and more powerful
> > > this way.
> >
> > Yeah, I agree, just the 3rd callback of release_io_cmd_t isn't covered
> > in this function.
> >
> > >
> > > Other than that bpf plumbing looks good.
> > >
> > > There is an issue with leaking allocated memory in bpf_aio_alloc kfunc
> > > (it probably should be KF_ACQUIRE)
> >
> > It is one problem which troubles me too:
> >
> > - another callback of struct_ops/bpf_aio_complete_cb is guaranteed to be
> > called after the 'struct bpf_aio' instance is submitted via kfunc
> > bpf_aio_submit(), and it is supposed to be freed from
> > struct_ops/bpf_aio_complete_cb
> >
> > - but the following verifier failure is triggered if bpf_aio_alloc and
> > bpf_aio_release are marked as KF_ACQUIRE & KF_RELEASE.
> >
> > ```
> > libbpf: prog 'ublk_loop_comp_cb': -- BEGIN PROG LOAD LOG --
> > Global function ublk_loop_comp_cb() doesn't return scalar. Only those are supported.
> > ```
> 
> That's odd.
> Adding KF_ACQ/REL to bpf_aio_alloc/release kfuncs shouldn't affect
> verification of ublk_loop_comp_cb() prog. It's fine for it to stay 'void'
> return.
> You probably made it global function and that's was the reason for this
> verifier error. Global funcs have to return scalar for now.
> We can relax this restriction if necessary.

Looks marking ublk_loop_comp_cb() as static doesn't work:

[root@ktest-40 ublk]# make
  CLNG-BPF ublk_loop.bpf.o
  GEN-SKEL ublk_loop.skel.h
libbpf: relocation against STT_SECTION in non-exec section is not supported!
Error: failed to link '/root/git/linux/tools/testing/selftests/ublk/ublk_loop.bpf.o': Invalid argument (22)

But seems not big deal because we can change its return type to 'int'.

> 
> >
> > Here 'struct bpf_aio' instance isn't stored in map, and it is provided
> > from struct_ops callback(bpf_aio_complete_cb), I appreciate you may share
> > any idea about how to let KF_ACQUIRE/KF_RELEASE cover the usage here.
> 
> This is so that:
> 
> ublk_loop_comp_cb ->
>   ublk_loop_comp_and_release_aio ->
>     bpf_aio_release
> 
> would properly recognize that ref to aio is dropped?
> 
> Currently the verifier doesn't support that,
> but there is work in progress to add this feature:
> 
> https://lore.kernel.org/bpf/20241220195619.2022866-2-amery.hung@gmail.com/
> 
> then in cfi_stabs annotated bio argument in bpf_aio_complete_cb()
> as "struct bpf_aio *aio__ref"
> 
> Then the verifier will recognize that callback argument
> comes refcounted and the prog has to call KF_RELEASE kfunc on it.

This looks one very nice feature, thanks for sharing it!

I tried to apply the above patch and patch 3 on next tree and pass 'aio__ref' to the
callback cfi_stabs, but still failed:

[root@ktest-40 ublk]# ./test_loop_01.sh
libbpf: prog 'ublk_loop_comp_cb': BPF program load failed: -EINVAL
libbpf: prog 'ublk_loop_comp_cb': -- BEGIN PROG LOAD LOG --
0: R1=ctx() R10=fp0
; int BPF_PROG(ublk_loop_comp_cb, struct bpf_aio *aio, long ret) @ ublk_loop.c:34
0: (79) r7 = *(u64 *)(r1 +8)          ; R1=ctx() R7_w=scalar()
1: (79) r6 = *(u64 *)(r1 +0)
func 'bpf_aio_complete_cb' arg0 has btf_id 37354 type STRUCT 'bpf_aio'
2: R1=ctx() R6_w=trusted_ptr_bpf_aio()
; struct ublk_bpf_io *io = ublk_bpf_acquire_io_from_aio(aio); @ ublk_loop.c:24
2: (bf) r1 = r6                       ; R1_w=trusted_ptr_bpf_aio() R6_w=trusted_ptr_bpf_aio()
3: (85) call ublk_bpf_acquire_io_from_aio#43231       ; R0_w=ptr_ublk_bpf_io(ref_obj_id=1) refs=1
4: (bf) r8 = r0                       ; R0_w=ptr_ublk_bpf_io(ref_obj_id=1) R8_w=ptr_ublk_bpf_io(ref_obj_id=1) refs=1
; ublk_bpf_complete_io(io, ret); @ ublk_loop.c:26
5: (bf) r1 = r8                       ; R1_w=ptr_ublk_bpf_io(ref_obj_id=1) R8_w=ptr_ublk_bpf_io(ref_obj_id=1) refs=1
6: (bc) w2 = w7                       ; R2_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff)) R7_w=scalar() refs=1
7: (85) call ublk_bpf_complete_io#43241       ; refs=1
; ublk_bpf_release_io_from_aio(io); @ ublk_loop.c:27
8: (bf) r1 = r8                       ; R1_w=ptr_ublk_bpf_io(ref_obj_id=1) R8=ptr_ublk_bpf_io(ref_obj_id=1) refs=1
9: (85) call ublk_bpf_release_io_from_aio#43257       ;
; ublk_bpf_dettach_and_complete_aio(aio); @ ublk_loop.c:29
10: (bf) r1 = r6                      ; R1_w=trusted_ptr_bpf_aio() R6=trusted_ptr_bpf_aio()
11: (85) call ublk_bpf_dettach_and_complete_aio#43245         ;
; bpf_aio_release(aio); @ ublk_loop.c:30
12: (bf) r1 = r6                      ; R1_w=trusted_ptr_bpf_aio() R6=trusted_ptr_bpf_aio()
13: (85) call bpf_aio_release#95841
release kernel function bpf_aio_release expects refcounted PTR_TO_BTF_ID
processed 14 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 1
-- END PROG LOAD LOG --
libbpf: prog 'ublk_loop_comp_cb': failed to load: -EINVAL
libbpf: failed to load object 'ublk_loop.bpf.o'
fail to load bpf obj from ublk_loop.bpf.o
fail to register bpf prog loop ublk_loop.bpf.o



Thanks,
Ming

  reply	other threads:[~2025-01-15 11:58 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-07 12:03 [RFC PATCH 00/22] ublk: support bpf Ming Lei
2025-01-07 12:03 ` [RFC PATCH 01/22] ublk: remove two unused fields from 'struct ublk_queue' Ming Lei
2025-01-07 12:03 ` [RFC PATCH 02/22] ublk: convert several bool type fields into bitfield of `ublk_queue` Ming Lei
2025-01-07 12:03 ` [RFC PATCH 03/22] ublk: add helper of ublk_need_map_io() Ming Lei
2025-01-07 12:03 ` [RFC PATCH 04/22] ublk: move ublk into one standalone directory Ming Lei
2025-01-07 12:03 ` [RFC PATCH 05/22] ublk: move private definitions into private header Ming Lei
2025-01-07 12:03 ` [RFC PATCH 06/22] ublk: move several helpers to " Ming Lei
2025-01-07 12:03 ` [RFC PATCH 07/22] ublk: bpf: add bpf prog attach helpers Ming Lei
2025-01-07 12:03 ` [RFC PATCH 08/22] ublk: bpf: add bpf struct_ops Ming Lei
2025-01-10  1:43   ` Alexei Starovoitov
2025-01-13  4:08     ` Ming Lei
2025-01-13 21:30       ` Alexei Starovoitov
2025-01-15 11:58         ` Ming Lei [this message]
2025-01-15 20:11           ` Amery Hung
2025-01-07 12:04 ` [RFC PATCH 09/22] ublk: bpf: attach bpf prog to ublk device Ming Lei
2025-01-07 12:04 ` [RFC PATCH 10/22] ublk: bpf: add kfunc for ublk bpf prog Ming Lei
2025-01-07 12:04 ` [RFC PATCH 11/22] ublk: bpf: enable ublk-bpf Ming Lei
2025-01-07 12:04 ` [RFC PATCH 12/22] selftests: ublk: add tests for the ublk-bpf initial implementation Ming Lei
2025-01-07 12:04 ` [RFC PATCH 13/22] selftests: ublk: add tests for covering io split Ming Lei
2025-01-07 12:04 ` [RFC PATCH 14/22] selftests: ublk: add tests for covering redirecting to userspace Ming Lei
2025-01-07 12:04 ` [RFC PATCH 15/22] ublk: bpf: add bpf aio kfunc Ming Lei
2025-01-07 12:04 ` [RFC PATCH 16/22] ublk: bpf: add bpf aio struct_ops Ming Lei
2025-01-07 12:04 ` [RFC PATCH 17/22] ublk: bpf: attach bpf aio prog to ublk device Ming Lei
2025-01-07 12:04 ` [RFC PATCH 18/22] ublk: bpf: add several ublk bpf aio kfuncs Ming Lei
2025-01-07 12:04 ` [RFC PATCH 19/22] ublk: bpf: wire bpf aio with ublk io handling Ming Lei
2025-01-07 12:04 ` [RFC PATCH 20/22] selftests: add tests for ublk bpf aio Ming Lei
2025-01-07 12:04 ` [RFC PATCH 21/22] selftests: add tests for covering both bpf aio and split Ming Lei
2025-01-07 12:04 ` [RFC PATCH 22/22] ublk: document ublk-bpf & bpf-aio Ming Lei

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Z4ei40AVuX2sCTmE@fedora \
    --to=tom.leiming@gmail.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=ameryhung@gmail.com \
    --cc=ast@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=bpf@vger.kernel.org \
    --cc=linux-block@vger.kernel.org \
    --cc=martin.lau@kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).