diff mbox series

block: reuse original bio_vec array for integrity during clone

Message ID 20240702100753.2168-1-anuj20.g@samsung.com (mailing list archive)
State New, archived
Headers show
Series block: reuse original bio_vec array for integrity during clone | expand

Commit Message

Anuj Gupta July 2, 2024, 10:07 a.m. UTC
Modify bio_integrity_clone to reuse the original bvec array instead of
allocating and copying it, similar to how bio data path is cloned.

Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
---
 block/bio-integrity.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

Comments

Christoph Hellwig July 2, 2024, noon UTC | #1
This looks good on it's own:

Signed-off-by: Christoph Hellwig <hch@lst.de>

but while looking for potentially issues with it I noticed the
integrity_req_gap_back_merge / integrity_req_gap_front_merge helpers
that directly access bip->bip_vec.  Given how even the old clone
implementation always clones the entire bvec array this patch
isn't even making things worse on it's own, but if we get more uses
of biovec clones we'll probably run into issues there.

For nvme there current is only a single integrity segments, so we
can't ever hits this code (at least until we implement SGL support
for metadata, which would be really nice - any takers?).

For SCSI mpi3mr can set a virt_mask and supports multiple integrity
segments.  But I don't know if the two can be combined as the
virt_mask is only set when it is fronting nvme and it might or
might not support integrity data for that use case.
Martin K. Petersen July 3, 2024, 2:13 a.m. UTC | #2
Anuj,

> Modify bio_integrity_clone to reuse the original bvec array instead of
> allocating and copying it, similar to how bio data path is cloned.

Pointing to the original bvec array when cloning was the original
approach. I'm not sure how we ended up copying, presumably that was done
as part of the iter conversion efforts. In any case this change is fine
with me.

Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Ming Lei July 3, 2024, 3:08 a.m. UTC | #3
On Tue, Jul 2, 2024 at 7:38 PM Anuj Gupta <anuj20.g@samsung.com> wrote:
>
> Modify bio_integrity_clone to reuse the original bvec array instead of
> allocating and copying it, similar to how bio data path is cloned.
>
> Suggested-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
> ---
>  block/bio-integrity.c | 9 +++------
>  1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/block/bio-integrity.c b/block/bio-integrity.c
> index c4aed1dfa497..b78c145eb026 100644
> --- a/block/bio-integrity.c
> +++ b/block/bio-integrity.c
> @@ -76,7 +76,7 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
>                                           &bip->bip_max_vcnt, gfp_mask);
>                 if (!bip->bip_vec)
>                         goto err;
> -       } else {
> +       } else if (nr_vecs) {
>                 bip->bip_vec = bip->bip_inline_vecs;
>         }
>
> @@ -584,14 +584,11 @@ int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
>
>         BUG_ON(bip_src == NULL);
>
> -       bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
> +       bip = bio_integrity_alloc(bio, gfp_mask, 0);
>         if (IS_ERR(bip))
>                 return PTR_ERR(bip);
>
> -       memcpy(bip->bip_vec, bip_src->bip_vec,
> -              bip_src->bip_vcnt * sizeof(struct bio_vec));
> -
> -       bip->bip_vcnt = bip_src->bip_vcnt;
> +       bip->bip_vec = bip_src->bip_vec;
>         bip->bip_iter = bip_src->bip_iter;
>         bip->bip_flags = bip_src->bip_flags & ~BIP_BLOCK_INTEGRITY;

I am curious how the patch avoids double free? Given nothing changes
in bip free code path and source bip_vec is associated with this bip.

Thanks,
Christoph Hellwig July 3, 2024, 4:46 a.m. UTC | #4
On Wed, Jul 03, 2024 at 11:08:49AM +0800, Ming Lei wrote:
> > -       bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
> > +       bip = bio_integrity_alloc(bio, gfp_mask, 0);
> >         if (IS_ERR(bip))
> >                 return PTR_ERR(bip);
> >
> > -       memcpy(bip->bip_vec, bip_src->bip_vec,
> > -              bip_src->bip_vcnt * sizeof(struct bio_vec));
> > -
> > -       bip->bip_vcnt = bip_src->bip_vcnt;
> > +       bip->bip_vec = bip_src->bip_vec;
> >         bip->bip_iter = bip_src->bip_iter;
> >         bip->bip_flags = bip_src->bip_flags & ~BIP_BLOCK_INTEGRITY;
> 
> I am curious how the patch avoids double free? Given nothing changes
> in bip free code path and source bip_vec is associated with this bip.

bvec_free only frees the bvec array if nr_vecs is > BIO_INLINE_VECS.
bio_integrity_clone now passes 0 as nr_vecs to bio_integrity_alloc
so it won't ever free the bvec array.  This matches what we are
doing for the data bvec array in the bio.
Ming Lei July 3, 2024, 5:16 a.m. UTC | #5
On Wed, Jul 3, 2024 at 12:46 PM Christoph Hellwig <hch@lst.de> wrote:
>
> On Wed, Jul 03, 2024 at 11:08:49AM +0800, Ming Lei wrote:
> > > -       bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
> > > +       bip = bio_integrity_alloc(bio, gfp_mask, 0);
> > >         if (IS_ERR(bip))
> > >                 return PTR_ERR(bip);
> > >
> > > -       memcpy(bip->bip_vec, bip_src->bip_vec,
> > > -              bip_src->bip_vcnt * sizeof(struct bio_vec));
> > > -
> > > -       bip->bip_vcnt = bip_src->bip_vcnt;
> > > +       bip->bip_vec = bip_src->bip_vec;
> > >         bip->bip_iter = bip_src->bip_iter;
> > >         bip->bip_flags = bip_src->bip_flags & ~BIP_BLOCK_INTEGRITY;
> >
> > I am curious how the patch avoids double free? Given nothing changes
> > in bip free code path and source bip_vec is associated with this bip.
>
> bvec_free only frees the bvec array if nr_vecs is > BIO_INLINE_VECS.
> bio_integrity_clone now passes 0 as nr_vecs to bio_integrity_alloc
> so it won't ever free the bvec array.  This matches what we are
> doing for the data bvec array in the bio.

OK, thanks for the clarification!

Reviewed-by: Ming Lei <ming.lei@redhat.com>
Jens Axboe July 4, 2024, 8:08 a.m. UTC | #6
On Tue, 02 Jul 2024 15:37:53 +0530, Anuj Gupta wrote:
> Modify bio_integrity_clone to reuse the original bvec array instead of
> allocating and copying it, similar to how bio data path is cloned.
> 
> 

Applied, thanks!

[1/1] block: reuse original bio_vec array for integrity during clone
      commit: ba942238056584efd3adc278a76592258d500918

Best regards,
diff mbox series

Patch

diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index c4aed1dfa497..b78c145eb026 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -76,7 +76,7 @@  struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
 					  &bip->bip_max_vcnt, gfp_mask);
 		if (!bip->bip_vec)
 			goto err;
-	} else {
+	} else if (nr_vecs) {
 		bip->bip_vec = bip->bip_inline_vecs;
 	}
 
@@ -584,14 +584,11 @@  int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
 
 	BUG_ON(bip_src == NULL);
 
-	bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
+	bip = bio_integrity_alloc(bio, gfp_mask, 0);
 	if (IS_ERR(bip))
 		return PTR_ERR(bip);
 
-	memcpy(bip->bip_vec, bip_src->bip_vec,
-	       bip_src->bip_vcnt * sizeof(struct bio_vec));
-
-	bip->bip_vcnt = bip_src->bip_vcnt;
+	bip->bip_vec = bip_src->bip_vec;
 	bip->bip_iter = bip_src->bip_iter;
 	bip->bip_flags = bip_src->bip_flags & ~BIP_BLOCK_INTEGRITY;