Linux block layer
 help / color / mirror / Atom feed
* [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends
@ 2026-05-20 20:36 Caleb Sander Mateos
  2026-05-20 20:36 ` [PATCH 7.2 1/2] ublk: move ublk_req_build_flags() earlier Caleb Sander Mateos
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Caleb Sander Mateos @ 2026-05-20 20:36 UTC (permalink / raw)
  To: Ming Lei, Jens Axboe; +Cc: linux-block, linux-kernel, Caleb Sander Mateos

Commit 4d4a512a1f87 ("ublk: add PFN-based buffer matching in I/O path")
added support to ublk_setup_iod() for matching request buffers against
registered UBLK_F_SHMEM_ZC buffers, but missed adding it to
ublk_setup_iod_zoned() for zoned requests. ublk_setup_iod_zoned()
duplicates the code for initializing struct ublksrv_io_desc, making it
easy to forget to keep them in sync. Move the common code to a helper
function ublk_init_iod(). This allows zone appends to leverage the
shared memory zero copy optimization.

This series is based on "ublk: optimize ublk_rq_has_data()" [1]

[1]: https://lore.kernel.org/linux-block/20260513211846.1956810-1-csander@purestorage.com/

Caleb Sander Mateos (2):
  ublk: move ublk_req_build_flags() earlier
  ublk: factor out ublk_init_iod() helper

 drivers/block/ublk_drv.c | 123 +++++++++++++++++++--------------------
 1 file changed, 60 insertions(+), 63 deletions(-)

-- 
2.54.0


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

* [PATCH 7.2 1/2] ublk: move ublk_req_build_flags() earlier
  2026-05-20 20:36 [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends Caleb Sander Mateos
@ 2026-05-20 20:36 ` Caleb Sander Mateos
  2026-05-20 20:36 ` [PATCH 7.2 2/2] ublk: factor out ublk_init_iod() helper Caleb Sander Mateos
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Caleb Sander Mateos @ 2026-05-20 20:36 UTC (permalink / raw)
  To: Ming Lei, Jens Axboe; +Cc: linux-block, linux-kernel, Caleb Sander Mateos

Move ublk_req_build_flags() above its callers so it doesn't need to be
forward-declared.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
 drivers/block/ublk_drv.c | 63 ++++++++++++++++++++--------------------
 1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 4d7efc12247c..0cb29be561b5 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -357,11 +357,10 @@ static bool ublk_try_buf_match(struct ublk_device *ub, struct request *rq,
 				  u32 *buf_idx, u32 *buf_off);
 static void ublk_buf_cleanup(struct ublk_device *ub);
 static void ublk_abort_queue(struct ublk_device *ub, struct ublk_queue *ubq);
 static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
 		u16 q_id, u16 tag, struct ublk_io *io);
-static inline unsigned int ublk_req_build_flags(struct request *req);
 static void ublk_batch_dispatch(struct ublk_queue *ubq,
 				const struct ublk_batch_io_data *data,
 				struct ublk_batch_fetch_cmd *fcmd);
 
 static inline bool ublk_dev_support_batch_io(const struct ublk_device *ub)
@@ -469,10 +468,41 @@ static inline bool ublk_queue_is_zoned(const struct ublk_queue *ubq)
 static inline bool ublk_dev_support_integrity(const struct ublk_device *ub)
 {
 	return ub->dev_info.flags & UBLK_F_INTEGRITY;
 }
 
+static inline unsigned int ublk_req_build_flags(struct request *req)
+{
+	unsigned flags = 0;
+
+	if (req->cmd_flags & REQ_FAILFAST_DEV)
+		flags |= UBLK_IO_F_FAILFAST_DEV;
+
+	if (req->cmd_flags & REQ_FAILFAST_TRANSPORT)
+		flags |= UBLK_IO_F_FAILFAST_TRANSPORT;
+
+	if (req->cmd_flags & REQ_FAILFAST_DRIVER)
+		flags |= UBLK_IO_F_FAILFAST_DRIVER;
+
+	if (req->cmd_flags & REQ_META)
+		flags |= UBLK_IO_F_META;
+
+	if (req->cmd_flags & REQ_FUA)
+		flags |= UBLK_IO_F_FUA;
+
+	if (req->cmd_flags & REQ_NOUNMAP)
+		flags |= UBLK_IO_F_NOUNMAP;
+
+	if (req->cmd_flags & REQ_SWAP)
+		flags |= UBLK_IO_F_SWAP;
+
+	if (blk_integrity_rq(req))
+		flags |= UBLK_IO_F_INTEGRITY;
+
+	return flags;
+}
+
 #ifdef CONFIG_BLK_DEV_ZONED
 
 struct ublk_zoned_report_desc {
 	__u64 sector;
 	__u32 operation;
@@ -1436,41 +1466,10 @@ static unsigned int ublk_unmap_io(bool need_map,
 		return ublk_copy_user_pages(req, 0, &iter, dir);
 	}
 	return rq_bytes;
 }
 
-static inline unsigned int ublk_req_build_flags(struct request *req)
-{
-	unsigned flags = 0;
-
-	if (req->cmd_flags & REQ_FAILFAST_DEV)
-		flags |= UBLK_IO_F_FAILFAST_DEV;
-
-	if (req->cmd_flags & REQ_FAILFAST_TRANSPORT)
-		flags |= UBLK_IO_F_FAILFAST_TRANSPORT;
-
-	if (req->cmd_flags & REQ_FAILFAST_DRIVER)
-		flags |= UBLK_IO_F_FAILFAST_DRIVER;
-
-	if (req->cmd_flags & REQ_META)
-		flags |= UBLK_IO_F_META;
-
-	if (req->cmd_flags & REQ_FUA)
-		flags |= UBLK_IO_F_FUA;
-
-	if (req->cmd_flags & REQ_NOUNMAP)
-		flags |= UBLK_IO_F_NOUNMAP;
-
-	if (req->cmd_flags & REQ_SWAP)
-		flags |= UBLK_IO_F_SWAP;
-
-	if (blk_integrity_rq(req))
-		flags |= UBLK_IO_F_INTEGRITY;
-
-	return flags;
-}
-
 static blk_status_t ublk_setup_iod(struct ublk_queue *ubq, struct request *req)
 {
 	struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
 	struct ublk_io *io = &ubq->ios[req->tag];
 	u32 ublk_op;
-- 
2.54.0


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

* [PATCH 7.2 2/2] ublk: factor out ublk_init_iod() helper
  2026-05-20 20:36 [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends Caleb Sander Mateos
  2026-05-20 20:36 ` [PATCH 7.2 1/2] ublk: move ublk_req_build_flags() earlier Caleb Sander Mateos
@ 2026-05-20 20:36 ` Caleb Sander Mateos
  2026-05-22  1:53 ` [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends Ming Lei
  2026-05-22 14:06 ` Jens Axboe
  3 siblings, 0 replies; 5+ messages in thread
From: Caleb Sander Mateos @ 2026-05-20 20:36 UTC (permalink / raw)
  To: Ming Lei, Jens Axboe; +Cc: linux-block, linux-kernel, Caleb Sander Mateos

The code for initializing struct ublksrv_io_desc on I/O dispatch is
largely duplicated in 3 places. Commit 4d4a512a1f87 ("ublk: add PFN-
based buffer matching in I/O path") added support to ublk_setup_iod()
for matching request buffers against registered UBLK_F_SHMEM_ZC buffers,
but missed adding it to ublk_setup_iod_zoned() for zoned requests. Move
the duplicated logic to a new helper ublk_init_iod(). This way, zone
appends can also benefit from avoiding the data copy.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
 drivers/block/ublk_drv.c | 60 +++++++++++++++++++---------------------
 1 file changed, 29 insertions(+), 31 deletions(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 0cb29be561b5..49624e65fe75 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -499,10 +499,35 @@ static inline unsigned int ublk_req_build_flags(struct request *req)
 		flags |= UBLK_IO_F_INTEGRITY;
 
 	return flags;
 }
 
+static void ublk_init_iod(struct ublk_queue *ubq, struct request *req,
+			  uint8_t ublk_op, uint32_t nr_sectors,
+			  uint64_t start_sector)
+{
+	struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
+	struct ublk_io *io = &ubq->ios[req->tag];
+
+	iod->op_flags = ublk_op | ublk_req_build_flags(req);
+	iod->nr_sectors = nr_sectors;
+	iod->start_sector = start_sector;
+
+	/* Try shmem zero-copy match before setting addr */
+	if (ublk_support_shmem_zc(ubq) && blk_rq_has_data(req)) {
+		u32 buf_idx, buf_off;
+
+		if (ublk_try_buf_match(ubq->dev, req, &buf_idx, &buf_off)) {
+			iod->op_flags |= UBLK_IO_F_SHMEM_ZC;
+			iod->addr = ublk_shmem_zc_addr(buf_idx, buf_off);
+			return;
+		}
+	}
+
+	iod->addr = io->buf.addr;
+}
+
 #ifdef CONFIG_BLK_DEV_ZONED
 
 struct ublk_zoned_report_desc {
 	__u64 sector;
 	__u32 operation;
@@ -680,12 +705,10 @@ static int ublk_report_zones(struct gendisk *disk, sector_t sector,
 }
 
 static blk_status_t ublk_setup_iod_zoned(struct ublk_queue *ubq,
 					 struct request *req)
 {
-	struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
-	struct ublk_io *io = &ubq->ios[req->tag];
 	struct ublk_zoned_report_desc *desc;
 	u32 ublk_op;
 
 	switch (req_op(req)) {
 	case REQ_OP_ZONE_OPEN:
@@ -711,13 +734,12 @@ static blk_status_t ublk_setup_iod_zoned(struct ublk_queue *ubq,
 		if (!desc)
 			return BLK_STS_IOERR;
 		ublk_op = desc->operation;
 		switch (ublk_op) {
 		case UBLK_IO_OP_REPORT_ZONES:
-			iod->op_flags = ublk_op | ublk_req_build_flags(req);
-			iod->nr_zones = desc->nr_zones;
-			iod->start_sector = desc->sector;
+			ublk_init_iod(ubq, req, ublk_op, desc->nr_zones,
+				      desc->sector);
 			return BLK_STS_OK;
 		default:
 			return BLK_STS_IOERR;
 		}
 	case REQ_OP_DRV_OUT:
@@ -725,15 +747,11 @@ static blk_status_t ublk_setup_iod_zoned(struct ublk_queue *ubq,
 		return BLK_STS_NOTSUPP;
 	default:
 		return BLK_STS_IOERR;
 	}
 
-	iod->op_flags = ublk_op | ublk_req_build_flags(req);
-	iod->nr_sectors = blk_rq_sectors(req);
-	iod->start_sector = blk_rq_pos(req);
-	iod->addr = io->buf.addr;
-
+	ublk_init_iod(ubq, req, ublk_op, blk_rq_sectors(req), blk_rq_pos(req));
 	return BLK_STS_OK;
 }
 
 #else
 
@@ -1468,12 +1486,10 @@ static unsigned int ublk_unmap_io(bool need_map,
 	return rq_bytes;
 }
 
 static blk_status_t ublk_setup_iod(struct ublk_queue *ubq, struct request *req)
 {
-	struct ublksrv_io_desc *iod = ublk_get_iod(ubq, req->tag);
-	struct ublk_io *io = &ubq->ios[req->tag];
 	u32 ublk_op;
 
 	switch (req_op(req)) {
 	case REQ_OP_READ:
 		ublk_op = UBLK_IO_OP_READ;
@@ -1494,29 +1510,11 @@ static blk_status_t ublk_setup_iod(struct ublk_queue *ubq, struct request *req)
 		if (ublk_queue_is_zoned(ubq))
 			return ublk_setup_iod_zoned(ubq, req);
 		return BLK_STS_IOERR;
 	}
 
-	/* need to translate since kernel may change */
-	iod->op_flags = ublk_op | ublk_req_build_flags(req);
-	iod->nr_sectors = blk_rq_sectors(req);
-	iod->start_sector = blk_rq_pos(req);
-
-	/* Try shmem zero-copy match before setting addr */
-	if (ublk_support_shmem_zc(ubq) && blk_rq_has_data(req)) {
-		u32 buf_idx, buf_off;
-
-		if (ublk_try_buf_match(ubq->dev, req,
-					  &buf_idx, &buf_off)) {
-			iod->op_flags |= UBLK_IO_F_SHMEM_ZC;
-			iod->addr = ublk_shmem_zc_addr(buf_idx, buf_off);
-			return BLK_STS_OK;
-		}
-	}
-
-	iod->addr = io->buf.addr;
-
+	ublk_init_iod(ubq, req, ublk_op, blk_rq_sectors(req), blk_rq_pos(req));
 	return BLK_STS_OK;
 }
 
 static inline struct ublk_uring_cmd_pdu *ublk_get_uring_cmd_pdu(
 		struct io_uring_cmd *ioucmd)
-- 
2.54.0


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

* Re: [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends
  2026-05-20 20:36 [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends Caleb Sander Mateos
  2026-05-20 20:36 ` [PATCH 7.2 1/2] ublk: move ublk_req_build_flags() earlier Caleb Sander Mateos
  2026-05-20 20:36 ` [PATCH 7.2 2/2] ublk: factor out ublk_init_iod() helper Caleb Sander Mateos
@ 2026-05-22  1:53 ` Ming Lei
  2026-05-22 14:06 ` Jens Axboe
  3 siblings, 0 replies; 5+ messages in thread
From: Ming Lei @ 2026-05-22  1:53 UTC (permalink / raw)
  To: Caleb Sander Mateos; +Cc: Jens Axboe, linux-block, linux-kernel

On Wed, May 20, 2026 at 02:36:52PM -0600, Caleb Sander Mateos wrote:
> Commit 4d4a512a1f87 ("ublk: add PFN-based buffer matching in I/O path")
> added support to ublk_setup_iod() for matching request buffers against
> registered UBLK_F_SHMEM_ZC buffers, but missed adding it to
> ublk_setup_iod_zoned() for zoned requests. ublk_setup_iod_zoned()
> duplicates the code for initializing struct ublksrv_io_desc, making it
> easy to forget to keep them in sync. Move the common code to a helper
> function ublk_init_iod(). This allows zone appends to leverage the
> shared memory zero copy optimization.
> 
> This series is based on "ublk: optimize ublk_rq_has_data()" [1]
> 
> [1]: https://lore.kernel.org/linux-block/20260513211846.1956810-1-csander@purestorage.com/

Looks fine, it just allows the optimization for zone append.

Reviewed-by: Ming Lei <tom.leiming@gmail.com>

Thanks,
Ming

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

* Re: [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends
  2026-05-20 20:36 [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends Caleb Sander Mateos
                   ` (2 preceding siblings ...)
  2026-05-22  1:53 ` [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends Ming Lei
@ 2026-05-22 14:06 ` Jens Axboe
  3 siblings, 0 replies; 5+ messages in thread
From: Jens Axboe @ 2026-05-22 14:06 UTC (permalink / raw)
  To: Ming Lei, Caleb Sander Mateos; +Cc: linux-block, linux-kernel


On Wed, 20 May 2026 14:36:52 -0600, Caleb Sander Mateos wrote:
> Commit 4d4a512a1f87 ("ublk: add PFN-based buffer matching in I/O path")
> added support to ublk_setup_iod() for matching request buffers against
> registered UBLK_F_SHMEM_ZC buffers, but missed adding it to
> ublk_setup_iod_zoned() for zoned requests. ublk_setup_iod_zoned()
> duplicates the code for initializing struct ublksrv_io_desc, making it
> easy to forget to keep them in sync. Move the common code to a helper
> function ublk_init_iod(). This allows zone appends to leverage the
> shared memory zero copy optimization.
> 
> [...]

Applied, thanks!

[1/2] ublk: move ublk_req_build_flags() earlier
      commit: eee9224affae6c1bfd664e5b769e40e3ff099879
[2/2] ublk: factor out ublk_init_iod() helper
      commit: 23130b3ffcdb1568a9ef178ab3cba866e5486082

Best regards,
-- 
Jens Axboe




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

end of thread, other threads:[~2026-05-22 14:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-20 20:36 [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends Caleb Sander Mateos
2026-05-20 20:36 ` [PATCH 7.2 1/2] ublk: move ublk_req_build_flags() earlier Caleb Sander Mateos
2026-05-20 20:36 ` [PATCH 7.2 2/2] ublk: factor out ublk_init_iod() helper Caleb Sander Mateos
2026-05-22  1:53 ` [PATCH 7.2 0/2] ublk: enable UBLK_F_SHMEM_ZC on zone appends Ming Lei
2026-05-22 14:06 ` Jens Axboe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox