linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] block: unmap and free user mapped integrity via submitter
       [not found] <CGME20240513084939epcas5p4530be8e7fc62b8d4db694d6b5bca3a19@epcas5p4.samsung.com>
@ 2024-05-13  8:42 ` Anuj Gupta
  2024-05-20 15:49   ` Christoph Hellwig
  2024-06-03 16:37   ` Anuj gupta
  0 siblings, 2 replies; 4+ messages in thread
From: Anuj Gupta @ 2024-05-13  8:42 UTC (permalink / raw)
  To: axboe, hch, kbusch
  Cc: linux-nvme, linux-block, martin.petersen, Anuj Gupta,
	Kanchan Joshi

The user mapped intergity is copied back and unpinned by
bio_integrity_free which is a low-level routine. Do it via the submitter
rather than doing it in the low-level block layer code, to split the
submitter side from the consumer side of the bio.

Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
Signed-off-by: Kanchan Joshi <joshi.k@samsung.com>
---
Changes in v2:
- create a helper for unmap logic (Keith)
- return if integrity is not user-mapped (Jens)
- v1: https://lore.kernel.org/linux-block/20240510094429.2489-1-anuj20.g@samsung.com/
---
 block/bio-integrity.c     | 26 ++++++++++++++++++++++++--
 drivers/nvme/host/ioctl.c | 15 +++++++++++----
 include/linux/bio.h       |  4 ++++
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index 2e3e8e04961e..8b528e12136f 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -144,16 +144,38 @@ void bio_integrity_free(struct bio *bio)
 	struct bio_integrity_payload *bip = bio_integrity(bio);
 	struct bio_set *bs = bio->bi_pool;
 
+	if (bip->bip_flags & BIP_INTEGRITY_USER)
+		return;
 	if (bip->bip_flags & BIP_BLOCK_INTEGRITY)
 		kfree(bvec_virt(bip->bip_vec));
-	else if (bip->bip_flags & BIP_INTEGRITY_USER)
-		bio_integrity_unmap_user(bip);
 
 	__bio_integrity_free(bs, bip);
 	bio->bi_integrity = NULL;
 	bio->bi_opf &= ~REQ_INTEGRITY;
 }
 
+/**
+ * bio_integrity_unmap_free_user - Unmap and free bio user integrity payload
+ * @bio:	bio containing bip to be unmapped and freed
+ *
+ * Description: Used to unmap and free the user mapped integrity portion of a
+ * bio. Submitter attaching the user integrity buffer is responsible for
+ * unmapping and freeing it during completion.
+ */
+void bio_integrity_unmap_free_user(struct bio *bio)
+{
+	struct bio_integrity_payload *bip = bio_integrity(bio);
+	struct bio_set *bs = bio->bi_pool;
+
+	if (WARN_ON_ONCE(!(bip->bip_flags & BIP_INTEGRITY_USER)))
+		return;
+	bio_integrity_unmap_user(bip);
+	__bio_integrity_free(bs, bip);
+	bio->bi_integrity = NULL;
+	bio->bi_opf &= ~REQ_INTEGRITY;
+}
+EXPORT_SYMBOL(bio_integrity_unmap_free_user);
+
 /**
  * bio_integrity_add_page - Attach integrity metadata
  * @bio:	bio to update
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 499a8bb7cac7..2dff5933cae9 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -111,6 +111,13 @@ static struct request *nvme_alloc_user_request(struct request_queue *q,
 	return req;
 }
 
+static void nvme_unmap_bio(struct bio *bio)
+{
+	if (bio_integrity(bio))
+		bio_integrity_unmap_free_user(bio);
+	blk_rq_unmap_user(bio);
+}
+
 static int nvme_map_user_request(struct request *req, u64 ubuffer,
 		unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
 		u32 meta_seed, struct io_uring_cmd *ioucmd, unsigned int flags)
@@ -157,7 +164,7 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
 
 out_unmap:
 	if (bio)
-		blk_rq_unmap_user(bio);
+		nvme_unmap_bio(bio);
 out:
 	blk_mq_free_request(req);
 	return ret;
@@ -195,7 +202,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
 	if (result)
 		*result = le64_to_cpu(nvme_req(req)->result.u64);
 	if (bio)
-		blk_rq_unmap_user(bio);
+		nvme_unmap_bio(bio);
 	blk_mq_free_request(req);
 
 	if (effects)
@@ -406,7 +413,7 @@ static void nvme_uring_task_cb(struct io_uring_cmd *ioucmd,
 	struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
 
 	if (pdu->bio)
-		blk_rq_unmap_user(pdu->bio);
+		nvme_unmap_bio(pdu->bio);
 	io_uring_cmd_done(ioucmd, pdu->status, pdu->result, issue_flags);
 }
 
@@ -432,7 +439,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
 	 */
 	if (blk_rq_is_poll(req)) {
 		if (pdu->bio)
-			blk_rq_unmap_user(pdu->bio);
+			nvme_unmap_bio(pdu->bio);
 		io_uring_cmd_iopoll_done(ioucmd, pdu->result, pdu->status);
 	} else {
 		io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index d5379548d684..818e93612947 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -731,6 +731,7 @@ static inline bool bioset_initialized(struct bio_set *bs)
 		bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
 
 int bio_integrity_map_user(struct bio *bio, void __user *ubuf, ssize_t len, u32 seed);
+void bio_integrity_unmap_free_user(struct bio *bio);
 extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
 extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
 extern bool bio_integrity_prep(struct bio *);
@@ -807,6 +808,9 @@ static inline int bio_integrity_map_user(struct bio *bio, void __user *ubuf,
 {
 	return -EINVAL;
 }
+static inline void bio_integrity_unmap_free_user(struct bio *bio)
+{
+}
 
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] block: unmap and free user mapped integrity via submitter
  2024-05-13  8:42 ` [PATCH v2] block: unmap and free user mapped integrity via submitter Anuj Gupta
@ 2024-05-20 15:49   ` Christoph Hellwig
  2024-05-24 10:19     ` Kanchan Joshi
  2024-06-03 16:37   ` Anuj gupta
  1 sibling, 1 reply; 4+ messages in thread
From: Christoph Hellwig @ 2024-05-20 15:49 UTC (permalink / raw)
  To: Anuj Gupta
  Cc: axboe, hch, kbusch, linux-nvme, linux-block, martin.petersen,
	Kanchan Joshi

> diff --git a/block/bio-integrity.c b/block/bio-integrity.c
> index 2e3e8e04961e..8b528e12136f 100644
> --- a/block/bio-integrity.c
> +++ b/block/bio-integrity.c
> @@ -144,16 +144,38 @@ void bio_integrity_free(struct bio *bio)
>  	struct bio_integrity_payload *bip = bio_integrity(bio);
>  	struct bio_set *bs = bio->bi_pool;
>  
> +	if (bip->bip_flags & BIP_INTEGRITY_USER)
> +		return;
>  	if (bip->bip_flags & BIP_BLOCK_INTEGRITY)
>  		kfree(bvec_virt(bip->bip_vec));
> -	else if (bip->bip_flags & BIP_INTEGRITY_USER)
> -		bio_integrity_unmap_user(bip);
>  
>  	__bio_integrity_free(bs, bip);
>  	bio->bi_integrity = NULL;
>  	bio->bi_opf &= ~REQ_INTEGRITY;

This looks correct.  I wish we could go one step further (maybe
in a separate patch/series) to also move freeing the bio integrity
data to the callers.  In fact I wonder if there is any point in
doing this early separate free vs just doing it as part of the
final bio put.  With that we could also entirely remove the
BIP_INTEGRITY_USER flag.

Otherwise looks good:

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] block: unmap and free user mapped integrity via submitter
  2024-05-20 15:49   ` Christoph Hellwig
@ 2024-05-24 10:19     ` Kanchan Joshi
  0 siblings, 0 replies; 4+ messages in thread
From: Kanchan Joshi @ 2024-05-24 10:19 UTC (permalink / raw)
  To: Christoph Hellwig, Anuj Gupta
  Cc: axboe, kbusch, linux-nvme, linux-block, martin.petersen

On 5/20/2024 9:19 PM, Christoph Hellwig wrote:
>> diff --git a/block/bio-integrity.c b/block/bio-integrity.c
>> index 2e3e8e04961e..8b528e12136f 100644
>> --- a/block/bio-integrity.c
>> +++ b/block/bio-integrity.c
>> @@ -144,16 +144,38 @@ void bio_integrity_free(struct bio *bio)
>>   	struct bio_integrity_payload *bip = bio_integrity(bio);
>>   	struct bio_set *bs = bio->bi_pool;
>>   
>> +	if (bip->bip_flags & BIP_INTEGRITY_USER)
>> +		return;
>>   	if (bip->bip_flags & BIP_BLOCK_INTEGRITY)
>>   		kfree(bvec_virt(bip->bip_vec));
>> -	else if (bip->bip_flags & BIP_INTEGRITY_USER)
>> -		bio_integrity_unmap_user(bip);
>>   
>>   	__bio_integrity_free(bs, bip);
>>   	bio->bi_integrity = NULL;
>>   	bio->bi_opf &= ~REQ_INTEGRITY;
> 
> This looks correct.  I wish we could go one step further (maybe
> in a separate patch/series) to also move freeing the bio integrity
> data to the callers.  In fact I wonder if there is any point in
> doing this early separate free vs just doing it as part of the
> final bio put.

Tried to think in this direction in past.
But bio_put will not be called if bio is statically allocated. Currently 
that gets freed implicitly because bio_endio is called and it tries to 
free the integrity.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] block: unmap and free user mapped integrity via submitter
  2024-05-13  8:42 ` [PATCH v2] block: unmap and free user mapped integrity via submitter Anuj Gupta
  2024-05-20 15:49   ` Christoph Hellwig
@ 2024-06-03 16:37   ` Anuj gupta
  1 sibling, 0 replies; 4+ messages in thread
From: Anuj gupta @ 2024-06-03 16:37 UTC (permalink / raw)
  To: Anuj Gupta
  Cc: axboe, hch, kbusch, linux-nvme, linux-block, martin.petersen,
	Kanchan Joshi

On Mon, May 13, 2024 at 3:02 PM Anuj Gupta <anuj20.g@samsung.com> wrote:
>
> The user mapped intergity is copied back and unpinned by
> bio_integrity_free which is a low-level routine. Do it via the submitter
> rather than doing it in the low-level block layer code, to split the
> submitter side from the consumer side of the bio.
>
> Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
> Signed-off-by: Kanchan Joshi <joshi.k@samsung.com>
> ---
> Changes in v2:
> - create a helper for unmap logic (Keith)
> - return if integrity is not user-mapped (Jens)
> - v1: https://lore.kernel.org/linux-block/20240510094429.2489-1-anuj20.g@samsung.com/
> ---
>  block/bio-integrity.c     | 26 ++++++++++++++++++++++++--
>  drivers/nvme/host/ioctl.c | 15 +++++++++++----
>  include/linux/bio.h       |  4 ++++
>  3 files changed, 39 insertions(+), 6 deletions(-)
>
> diff --git a/block/bio-integrity.c b/block/bio-integrity.c
> index 2e3e8e04961e..8b528e12136f 100644
> --- a/block/bio-integrity.c
> +++ b/block/bio-integrity.c
> @@ -144,16 +144,38 @@ void bio_integrity_free(struct bio *bio)
>         struct bio_integrity_payload *bip = bio_integrity(bio);
>         struct bio_set *bs = bio->bi_pool;
>
> +       if (bip->bip_flags & BIP_INTEGRITY_USER)
> +               return;
>         if (bip->bip_flags & BIP_BLOCK_INTEGRITY)
>                 kfree(bvec_virt(bip->bip_vec));
> -       else if (bip->bip_flags & BIP_INTEGRITY_USER)
> -               bio_integrity_unmap_user(bip);
>
>         __bio_integrity_free(bs, bip);
>         bio->bi_integrity = NULL;
>         bio->bi_opf &= ~REQ_INTEGRITY;
>  }
>
> +/**
> + * bio_integrity_unmap_free_user - Unmap and free bio user integrity payload
> + * @bio:       bio containing bip to be unmapped and freed
> + *
> + * Description: Used to unmap and free the user mapped integrity portion of a
> + * bio. Submitter attaching the user integrity buffer is responsible for
> + * unmapping and freeing it during completion.
> + */
> +void bio_integrity_unmap_free_user(struct bio *bio)
> +{
> +       struct bio_integrity_payload *bip = bio_integrity(bio);
> +       struct bio_set *bs = bio->bi_pool;
> +
> +       if (WARN_ON_ONCE(!(bip->bip_flags & BIP_INTEGRITY_USER)))
> +               return;
> +       bio_integrity_unmap_user(bip);
> +       __bio_integrity_free(bs, bip);
> +       bio->bi_integrity = NULL;
> +       bio->bi_opf &= ~REQ_INTEGRITY;
> +}
> +EXPORT_SYMBOL(bio_integrity_unmap_free_user);
> +
>  /**
>   * bio_integrity_add_page - Attach integrity metadata
>   * @bio:       bio to update
> diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
> index 499a8bb7cac7..2dff5933cae9 100644
> --- a/drivers/nvme/host/ioctl.c
> +++ b/drivers/nvme/host/ioctl.c
> @@ -111,6 +111,13 @@ static struct request *nvme_alloc_user_request(struct request_queue *q,
>         return req;
>  }
>
> +static void nvme_unmap_bio(struct bio *bio)
> +{
> +       if (bio_integrity(bio))
> +               bio_integrity_unmap_free_user(bio);
> +       blk_rq_unmap_user(bio);
> +}
> +
>  static int nvme_map_user_request(struct request *req, u64 ubuffer,
>                 unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
>                 u32 meta_seed, struct io_uring_cmd *ioucmd, unsigned int flags)
> @@ -157,7 +164,7 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
>
>  out_unmap:
>         if (bio)
> -               blk_rq_unmap_user(bio);
> +               nvme_unmap_bio(bio);
>  out:
>         blk_mq_free_request(req);
>         return ret;
> @@ -195,7 +202,7 @@ static int nvme_submit_user_cmd(struct request_queue *q,
>         if (result)
>                 *result = le64_to_cpu(nvme_req(req)->result.u64);
>         if (bio)
> -               blk_rq_unmap_user(bio);
> +               nvme_unmap_bio(bio);
>         blk_mq_free_request(req);
>
>         if (effects)
> @@ -406,7 +413,7 @@ static void nvme_uring_task_cb(struct io_uring_cmd *ioucmd,
>         struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
>
>         if (pdu->bio)
> -               blk_rq_unmap_user(pdu->bio);
> +               nvme_unmap_bio(pdu->bio);
>         io_uring_cmd_done(ioucmd, pdu->status, pdu->result, issue_flags);
>  }
>
> @@ -432,7 +439,7 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
>          */
>         if (blk_rq_is_poll(req)) {
>                 if (pdu->bio)
> -                       blk_rq_unmap_user(pdu->bio);
> +                       nvme_unmap_bio(pdu->bio);
>                 io_uring_cmd_iopoll_done(ioucmd, pdu->result, pdu->status);
>         } else {
>                 io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb);
> diff --git a/include/linux/bio.h b/include/linux/bio.h
> index d5379548d684..818e93612947 100644
> --- a/include/linux/bio.h
> +++ b/include/linux/bio.h
> @@ -731,6 +731,7 @@ static inline bool bioset_initialized(struct bio_set *bs)
>                 bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
>
>  int bio_integrity_map_user(struct bio *bio, void __user *ubuf, ssize_t len, u32 seed);
> +void bio_integrity_unmap_free_user(struct bio *bio);
>  extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
>  extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
>  extern bool bio_integrity_prep(struct bio *);
> @@ -807,6 +808,9 @@ static inline int bio_integrity_map_user(struct bio *bio, void __user *ubuf,
>  {
>         return -EINVAL;
>  }
> +static inline void bio_integrity_unmap_free_user(struct bio *bio)
> +{
> +}
>
>  #endif /* CONFIG_BLK_DEV_INTEGRITY */
>
> --
> 2.25.1
>
>
Hi Jens,
This has got the necessary reviews. Can this be picked up?
Or do you see anything missing?

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-06-03 16:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CGME20240513084939epcas5p4530be8e7fc62b8d4db694d6b5bca3a19@epcas5p4.samsung.com>
2024-05-13  8:42 ` [PATCH v2] block: unmap and free user mapped integrity via submitter Anuj Gupta
2024-05-20 15:49   ` Christoph Hellwig
2024-05-24 10:19     ` Kanchan Joshi
2024-06-03 16:37   ` Anuj gupta

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).