public inbox for linux-block@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6.15 0/3] ublk: one selftest fix and two zero copy fixes
@ 2025-04-27 13:49 Ming Lei
  2025-04-27 13:49 ` [PATCH v6.15 1/3] selftests: ublk: fix UBLK_F_NEED_GET_DATA Ming Lei
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Ming Lei @ 2025-04-27 13:49 UTC (permalink / raw)
  To: Jens Axboe, linux-block
  Cc: Uday Shankar, Caleb Sander Mateos, Keith Busch, Ming Lei

Hello Jens,

The 1st patch fixes UBLK_F_NEED_GET_DATA support in ublk selftest side.

The other two patches enhances check for zero copy feature.

Thanks,
Ming


Ming Lei (3):
  selftests: ublk: fix UBLK_F_NEED_GET_DATA
  ublk: decouple zero copy from user copy
  ublk: enhance check for register/unregister io buffer command

 drivers/block/ublk_drv.c                      | 59 ++++++++++++++-----
 tools/testing/selftests/ublk/Makefile         |  1 +
 tools/testing/selftests/ublk/kublk.c          | 20 ++++---
 tools/testing/selftests/ublk/kublk.h          |  1 +
 .../testing/selftests/ublk/test_generic_07.sh | 24 ++++++++
 .../testing/selftests/ublk/test_stress_05.sh  |  8 +--
 6 files changed, 86 insertions(+), 27 deletions(-)
 create mode 100755 tools/testing/selftests/ublk/test_generic_07.sh

-- 
2.47.0


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

* [PATCH v6.15 1/3] selftests: ublk: fix UBLK_F_NEED_GET_DATA
  2025-04-27 13:49 [PATCH v6.15 0/3] ublk: one selftest fix and two zero copy fixes Ming Lei
@ 2025-04-27 13:49 ` Ming Lei
  2025-04-28 15:51   ` Caleb Sander Mateos
  2025-04-27 13:49 ` [PATCH v6.15 2/3] ublk: decouple zero copy from user copy Ming Lei
  2025-04-27 13:49 ` [PATCH v6.15 3/3] ublk: enhance check for register/unregister io buffer command Ming Lei
  2 siblings, 1 reply; 13+ messages in thread
From: Ming Lei @ 2025-04-27 13:49 UTC (permalink / raw)
  To: Jens Axboe, linux-block
  Cc: Uday Shankar, Caleb Sander Mateos, Keith Busch, Ming Lei

Commit 57e13a2e8cd2 ("selftests: ublk: support user recovery") starts to
support UBLK_F_NEED_GET_DATA for covering recovery feature, however the
ublk utility implementation isn't done correctly.

Fix it by supporting UBLK_F_NEED_GET_DATA correctly.

Also add test generic_07 for covering UBLK_F_NEED_GET_DATA.

Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
Fixes: 57e13a2e8cd2 ("selftests: ublk: support user recovery")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
 tools/testing/selftests/ublk/Makefile         |  1 +
 tools/testing/selftests/ublk/kublk.c          | 20 ++++++++++------
 tools/testing/selftests/ublk/kublk.h          |  1 +
 .../testing/selftests/ublk/test_generic_07.sh | 24 +++++++++++++++++++
 .../testing/selftests/ublk/test_stress_05.sh  |  8 +++----
 5 files changed, 43 insertions(+), 11 deletions(-)
 create mode 100755 tools/testing/selftests/ublk/test_generic_07.sh

diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile
index ec4624a283bc..f34ac0bac696 100644
--- a/tools/testing/selftests/ublk/Makefile
+++ b/tools/testing/selftests/ublk/Makefile
@@ -9,6 +9,7 @@ TEST_PROGS += test_generic_03.sh
 TEST_PROGS += test_generic_04.sh
 TEST_PROGS += test_generic_05.sh
 TEST_PROGS += test_generic_06.sh
+TEST_PROGS += test_generic_07.sh
 
 TEST_PROGS += test_null_01.sh
 TEST_PROGS += test_null_02.sh
diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index e57a1486bb48..3afd45d7f989 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -536,12 +536,17 @@ int ublk_queue_io_cmd(struct ublk_queue *q, struct ublk_io *io, unsigned tag)
 	if (!(io->flags & UBLKSRV_IO_FREE))
 		return 0;
 
-	/* we issue because we need either fetching or committing */
+	/*
+	 * we issue because we need either fetching or committing or
+	 * getting data
+	 */
 	if (!(io->flags &
-		(UBLKSRV_NEED_FETCH_RQ | UBLKSRV_NEED_COMMIT_RQ_COMP)))
+		(UBLKSRV_NEED_FETCH_RQ | UBLKSRV_NEED_COMMIT_RQ_COMP | UBLKSRV_NEED_GET_DATA)))
 		return 0;
 
-	if (io->flags & UBLKSRV_NEED_COMMIT_RQ_COMP)
+	if (io->flags & UBLKSRV_NEED_GET_DATA)
+		cmd_op = UBLK_U_IO_NEED_GET_DATA;
+	else if (io->flags & UBLKSRV_NEED_COMMIT_RQ_COMP)
 		cmd_op = UBLK_U_IO_COMMIT_AND_FETCH_REQ;
 	else if (io->flags & UBLKSRV_NEED_FETCH_RQ)
 		cmd_op = UBLK_U_IO_FETCH_REQ;
@@ -658,6 +663,9 @@ static void ublk_handle_cqe(struct io_uring *r,
 		assert(tag < q->q_depth);
 		if (q->tgt_ops->queue_io)
 			q->tgt_ops->queue_io(q, tag);
+	} else if (cqe->res == UBLK_IO_RES_NEED_GET_DATA) {
+		io->flags |= UBLKSRV_NEED_GET_DATA | UBLKSRV_IO_FREE;
+		ublk_queue_io_cmd(q, io, tag);
 	} else {
 		/*
 		 * COMMIT_REQ will be completed immediately since no fetching
@@ -1313,7 +1321,7 @@ int main(int argc, char *argv[])
 
 	opterr = 0;
 	optind = 2;
-	while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:az",
+	while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:gaz",
 				  longopts, &option_idx)) != -1) {
 		switch (opt) {
 		case 'a':
@@ -1351,9 +1359,7 @@ int main(int argc, char *argv[])
 				ctx.flags |= UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_REISSUE;
 			break;
 		case 'g':
-			value = strtol(optarg, NULL, 10);
-			if (value)
-				ctx.flags |= UBLK_F_NEED_GET_DATA;
+			ctx.flags |= UBLK_F_NEED_GET_DATA;
 			break;
 		case 0:
 			if (!strcmp(longopts[option_idx].name, "debug_mask"))
diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h
index 918db5cd633f..44ee1e4ac55b 100644
--- a/tools/testing/selftests/ublk/kublk.h
+++ b/tools/testing/selftests/ublk/kublk.h
@@ -115,6 +115,7 @@ struct ublk_io {
 #define UBLKSRV_NEED_FETCH_RQ		(1UL << 0)
 #define UBLKSRV_NEED_COMMIT_RQ_COMP	(1UL << 1)
 #define UBLKSRV_IO_FREE			(1UL << 2)
+#define UBLKSRV_NEED_GET_DATA           (1UL << 3)
 	unsigned short flags;
 	unsigned short refs;		/* used by target code only */
 
diff --git a/tools/testing/selftests/ublk/test_generic_07.sh b/tools/testing/selftests/ublk/test_generic_07.sh
new file mode 100755
index 000000000000..e3ad36ef7b9a
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_generic_07.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+TID="generic_07"
+ERR_CODE=0
+
+_prep_test "generic" "test UBLK_F_NEED_GET_DATA"
+
+_create_backfile 0 256M
+dev_id=$(_add_ublk_dev -t loop -q 2 -g "${UBLK_BACKFILES[0]}")
+_check_add_dev $TID $?
+
+# run fio over the ublk disk
+_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M
+ERR_CODE=$?
+if [ "$ERR_CODE" -eq 0 ]; then
+	_mkfs_mount_test /dev/ublkb"${dev_id}"
+	ERR_CODE=$?
+fi
+
+_cleanup_test "generic"
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_stress_05.sh b/tools/testing/selftests/ublk/test_stress_05.sh
index a7071b10224d..88601b48f1cd 100755
--- a/tools/testing/selftests/ublk/test_stress_05.sh
+++ b/tools/testing/selftests/ublk/test_stress_05.sh
@@ -47,15 +47,15 @@ _create_backfile 0 256M
 _create_backfile 1 256M
 
 for reissue in $(seq 0 1); do
-	ublk_io_and_remove 8G -t null -q 4 -g 1 -r 1 -i "$reissue" &
-	ublk_io_and_remove 256M -t loop -q 4 -g 1 -r 1 -i "$reissue" "${UBLK_BACKFILES[0]}" &
+	ublk_io_and_remove 8G -t null -q 4 -g -r 1 -i "$reissue" &
+	ublk_io_and_remove 256M -t loop -q 4 -g -r 1 -i "$reissue" "${UBLK_BACKFILES[0]}" &
 	wait
 done
 
 if _have_feature "ZERO_COPY"; then
 	for reissue in $(seq 0 1); do
-		ublk_io_and_remove 8G -t null -q 4 -g 1 -z -r 1 -i "$reissue" &
-		ublk_io_and_remove 256M -t loop -q 4 -g 1 -z -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
+		ublk_io_and_remove 8G -t null -q 4 -g -z -r 1 -i "$reissue" &
+		ublk_io_and_remove 256M -t loop -q 4 -g -z -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
 		wait
 	done
 fi
-- 
2.47.0


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

* [PATCH v6.15 2/3] ublk: decouple zero copy from user copy
  2025-04-27 13:49 [PATCH v6.15 0/3] ublk: one selftest fix and two zero copy fixes Ming Lei
  2025-04-27 13:49 ` [PATCH v6.15 1/3] selftests: ublk: fix UBLK_F_NEED_GET_DATA Ming Lei
@ 2025-04-27 13:49 ` Ming Lei
  2025-04-28 16:01   ` Caleb Sander Mateos
  2025-04-27 13:49 ` [PATCH v6.15 3/3] ublk: enhance check for register/unregister io buffer command Ming Lei
  2 siblings, 1 reply; 13+ messages in thread
From: Ming Lei @ 2025-04-27 13:49 UTC (permalink / raw)
  To: Jens Axboe, linux-block
  Cc: Uday Shankar, Caleb Sander Mateos, Keith Busch, Ming Lei

UBLK_F_USER_COPY and UBLK_F_SUPPORT_ZERO_COPY are two different
features, and shouldn't be coupled together.

Commit 1f6540e2aabb ("ublk: zc register/unregister bvec") enables
user copy automatically in case of UBLK_F_SUPPORT_ZERO_COPY, this way
isn't correct.

So decouple zero copy from user copy, and use independent helper to
check each one.

Fixes: 1f6540e2aabb ("ublk: zc register/unregister bvec")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
 drivers/block/ublk_drv.c | 35 +++++++++++++++++++++++------------
 1 file changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 40f971a66d3e..0a3a3c64316d 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -205,11 +205,6 @@ static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
 static inline unsigned int ublk_req_build_flags(struct request *req);
 static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
 						   int tag);
-static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)
-{
-	return ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
-}
-
 static inline bool ublk_dev_is_zoned(const struct ublk_device *ub)
 {
 	return ub->dev_info.flags & UBLK_F_ZONED;
@@ -609,14 +604,19 @@ static void ublk_apply_params(struct ublk_device *ub)
 		ublk_dev_param_zoned_apply(ub);
 }
 
+static inline bool ublk_support_zero_copy(const struct ublk_queue *ubq)
+{
+	return ubq->flags & UBLK_F_SUPPORT_ZERO_COPY;
+}
+
 static inline bool ublk_support_user_copy(const struct ublk_queue *ubq)
 {
-	return ubq->flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
+	return ubq->flags & UBLK_F_USER_COPY;
 }
 
 static inline bool ublk_need_map_io(const struct ublk_queue *ubq)
 {
-	return !ublk_support_user_copy(ubq);
+	return !ublk_support_user_copy(ubq) && !ublk_support_zero_copy(ubq);
 }
 
 static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
@@ -624,8 +624,11 @@ static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
 	/*
 	 * read()/write() is involved in user copy, so request reference
 	 * has to be grabbed
+	 *
+	 * for zero copy, request buffer need to be registered to io_uring
+	 * buffer table, so reference is needed
 	 */
-	return ublk_support_user_copy(ubq);
+	return ublk_support_user_copy(ubq) || ublk_support_zero_copy(ubq);
 }
 
 static inline void ublk_init_req_ref(const struct ublk_queue *ubq,
@@ -2245,6 +2248,9 @@ static struct request *ublk_check_and_get_req(struct kiocb *iocb,
 	if (!ubq)
 		return ERR_PTR(-EINVAL);
 
+	if (!ublk_support_user_copy(ubq))
+		return ERR_PTR(-EACCES);
+
 	if (tag >= ubq->q_depth)
 		return ERR_PTR(-EINVAL);
 
@@ -2783,13 +2789,18 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
 	ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE |
 		UBLK_F_URING_CMD_COMP_IN_TASK;
 
-	/* GET_DATA isn't needed any more with USER_COPY */
-	if (ublk_dev_is_user_copy(ub))
+	/* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */
+	if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY))
 		ub->dev_info.flags &= ~UBLK_F_NEED_GET_DATA;
 
-	/* Zoned storage support requires user copy feature */
+	/*
+	 * Zoned storage support requires reuse `ublksrv_io_cmd->addr` for
+	 * returning write_append_lba, which is only allowed in case of
+	 * user copy or zero copy
+	 */
 	if (ublk_dev_is_zoned(ub) &&
-	    (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) || !ublk_dev_is_user_copy(ub))) {
+	    (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) || !(ub->dev_info.flags &
+	     (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY)))) {
 		ret = -EINVAL;
 		goto out_free_dev_number;
 	}
-- 
2.47.0


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

* [PATCH v6.15 3/3] ublk: enhance check for register/unregister io buffer command
  2025-04-27 13:49 [PATCH v6.15 0/3] ublk: one selftest fix and two zero copy fixes Ming Lei
  2025-04-27 13:49 ` [PATCH v6.15 1/3] selftests: ublk: fix UBLK_F_NEED_GET_DATA Ming Lei
  2025-04-27 13:49 ` [PATCH v6.15 2/3] ublk: decouple zero copy from user copy Ming Lei
@ 2025-04-27 13:49 ` Ming Lei
  2025-04-28 16:28   ` Caleb Sander Mateos
  2 siblings, 1 reply; 13+ messages in thread
From: Ming Lei @ 2025-04-27 13:49 UTC (permalink / raw)
  To: Jens Axboe, linux-block
  Cc: Uday Shankar, Caleb Sander Mateos, Keith Busch, Ming Lei

The simple check of UBLK_IO_FLAG_OWNED_BY_SRV can avoid incorrect
register/unregister io buffer easily, so check it before calling
starting to register/un-register io buffer.

Also only allow io buffer register/unregister uring_cmd in case of
UBLK_F_SUPPORT_ZERO_COPY.

Also mark argument 'ublk_queue *' of ublk_register_io_buf as const.

Fixes: 1f6540e2aabb ("ublk: zc register/unregister bvec")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
 drivers/block/ublk_drv.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 0a3a3c64316d..c624d8f653ae 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -201,7 +201,7 @@ struct ublk_params_header {
 static void ublk_stop_dev_unlocked(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,
-		struct ublk_queue *ubq, int tag, size_t offset);
+		const struct ublk_queue *ubq, int tag, size_t offset);
 static inline unsigned int ublk_req_build_flags(struct request *req);
 static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
 						   int tag);
@@ -1949,13 +1949,20 @@ static void ublk_io_release(void *priv)
 }
 
 static int ublk_register_io_buf(struct io_uring_cmd *cmd,
-				struct ublk_queue *ubq, unsigned int tag,
+				const struct ublk_queue *ubq, unsigned int tag,
 				unsigned int index, unsigned int issue_flags)
 {
 	struct ublk_device *ub = cmd->file->private_data;
+	const struct ublk_io *io = &ubq->ios[tag];
 	struct request *req;
 	int ret;
 
+	if (!ublk_support_zero_copy(ubq))
+		return -EINVAL;
+
+	if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
+		return -EINVAL;
+
 	req = __ublk_check_and_get_req(ub, ubq, tag, 0);
 	if (!req)
 		return -EINVAL;
@@ -1971,8 +1978,17 @@ static int ublk_register_io_buf(struct io_uring_cmd *cmd,
 }
 
 static int ublk_unregister_io_buf(struct io_uring_cmd *cmd,
+				  const struct ublk_queue *ubq, unsigned int tag,
 				  unsigned int index, unsigned int issue_flags)
 {
+	const struct ublk_io *io = &ubq->ios[tag];
+
+	if (!ublk_support_zero_copy(ubq))
+		return -EINVAL;
+
+	if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
+		return -EINVAL;
+
 	return io_buffer_unregister_bvec(cmd, index, issue_flags);
 }
 
@@ -2076,7 +2092,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
 	case UBLK_IO_REGISTER_IO_BUF:
 		return ublk_register_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
 	case UBLK_IO_UNREGISTER_IO_BUF:
-		return ublk_unregister_io_buf(cmd, ub_cmd->addr, issue_flags);
+		return ublk_unregister_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
 	case UBLK_IO_FETCH_REQ:
 		ret = ublk_fetch(cmd, ubq, io, ub_cmd->addr);
 		if (ret)
@@ -2128,7 +2144,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
 }
 
 static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
-		struct ublk_queue *ubq, int tag, size_t offset)
+		const struct ublk_queue *ubq, int tag, size_t offset)
 {
 	struct request *req;
 
-- 
2.47.0


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

* Re: [PATCH v6.15 1/3] selftests: ublk: fix UBLK_F_NEED_GET_DATA
  2025-04-27 13:49 ` [PATCH v6.15 1/3] selftests: ublk: fix UBLK_F_NEED_GET_DATA Ming Lei
@ 2025-04-28 15:51   ` Caleb Sander Mateos
  2025-04-29  0:53     ` Ming Lei
  0 siblings, 1 reply; 13+ messages in thread
From: Caleb Sander Mateos @ 2025-04-28 15:51 UTC (permalink / raw)
  To: Ming Lei; +Cc: Jens Axboe, linux-block, Uday Shankar, Keith Busch

On Sun, Apr 27, 2025 at 6:49 AM Ming Lei <ming.lei@redhat.com> wrote:
>
> Commit 57e13a2e8cd2 ("selftests: ublk: support user recovery") starts to
> support UBLK_F_NEED_GET_DATA for covering recovery feature, however the
> ublk utility implementation isn't done correctly.
>
> Fix it by supporting UBLK_F_NEED_GET_DATA correctly.
>
> Also add test generic_07 for covering UBLK_F_NEED_GET_DATA.
>
> Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
> Fixes: 57e13a2e8cd2 ("selftests: ublk: support user recovery")
> Signed-off-by: Ming Lei <ming.lei@redhat.com>
> ---
>  tools/testing/selftests/ublk/Makefile         |  1 +
>  tools/testing/selftests/ublk/kublk.c          | 20 ++++++++++------
>  tools/testing/selftests/ublk/kublk.h          |  1 +
>  .../testing/selftests/ublk/test_generic_07.sh | 24 +++++++++++++++++++
>  .../testing/selftests/ublk/test_stress_05.sh  |  8 +++----
>  5 files changed, 43 insertions(+), 11 deletions(-)
>  create mode 100755 tools/testing/selftests/ublk/test_generic_07.sh
>
> diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile
> index ec4624a283bc..f34ac0bac696 100644
> --- a/tools/testing/selftests/ublk/Makefile
> +++ b/tools/testing/selftests/ublk/Makefile
> @@ -9,6 +9,7 @@ TEST_PROGS += test_generic_03.sh
>  TEST_PROGS += test_generic_04.sh
>  TEST_PROGS += test_generic_05.sh
>  TEST_PROGS += test_generic_06.sh
> +TEST_PROGS += test_generic_07.sh
>
>  TEST_PROGS += test_null_01.sh
>  TEST_PROGS += test_null_02.sh
> diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
> index e57a1486bb48..3afd45d7f989 100644
> --- a/tools/testing/selftests/ublk/kublk.c
> +++ b/tools/testing/selftests/ublk/kublk.c
> @@ -536,12 +536,17 @@ int ublk_queue_io_cmd(struct ublk_queue *q, struct ublk_io *io, unsigned tag)
>         if (!(io->flags & UBLKSRV_IO_FREE))
>                 return 0;
>
> -       /* we issue because we need either fetching or committing */
> +       /*
> +        * we issue because we need either fetching or committing or
> +        * getting data
> +        */
>         if (!(io->flags &
> -               (UBLKSRV_NEED_FETCH_RQ | UBLKSRV_NEED_COMMIT_RQ_COMP)))
> +               (UBLKSRV_NEED_FETCH_RQ | UBLKSRV_NEED_COMMIT_RQ_COMP | UBLKSRV_NEED_GET_DATA)))
>                 return 0;
>
> -       if (io->flags & UBLKSRV_NEED_COMMIT_RQ_COMP)
> +       if (io->flags & UBLKSRV_NEED_GET_DATA)
> +               cmd_op = UBLK_U_IO_NEED_GET_DATA;
> +       else if (io->flags & UBLKSRV_NEED_COMMIT_RQ_COMP)
>                 cmd_op = UBLK_U_IO_COMMIT_AND_FETCH_REQ;
>         else if (io->flags & UBLKSRV_NEED_FETCH_RQ)
>                 cmd_op = UBLK_U_IO_FETCH_REQ;
> @@ -658,6 +663,9 @@ static void ublk_handle_cqe(struct io_uring *r,
>                 assert(tag < q->q_depth);
>                 if (q->tgt_ops->queue_io)
>                         q->tgt_ops->queue_io(q, tag);
> +       } else if (cqe->res == UBLK_IO_RES_NEED_GET_DATA) {
> +               io->flags |= UBLKSRV_NEED_GET_DATA | UBLKSRV_IO_FREE;
> +               ublk_queue_io_cmd(q, io, tag);
>         } else {
>                 /*
>                  * COMMIT_REQ will be completed immediately since no fetching
> @@ -1313,7 +1321,7 @@ int main(int argc, char *argv[])
>
>         opterr = 0;
>         optind = 2;
> -       while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:az",
> +       while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:gaz",
>                                   longopts, &option_idx)) != -1) {
>                 switch (opt) {
>                 case 'a':
> @@ -1351,9 +1359,7 @@ int main(int argc, char *argv[])
>                                 ctx.flags |= UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_REISSUE;
>                         break;
>                 case 'g':
> -                       value = strtol(optarg, NULL, 10);
> -                       if (value)
> -                               ctx.flags |= UBLK_F_NEED_GET_DATA;
> +                       ctx.flags |= UBLK_F_NEED_GET_DATA;

The help text in __cmd_create_help() should be updated accordingly.

>                         break;
>                 case 0:
>                         if (!strcmp(longopts[option_idx].name, "debug_mask"))
> diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h
> index 918db5cd633f..44ee1e4ac55b 100644
> --- a/tools/testing/selftests/ublk/kublk.h
> +++ b/tools/testing/selftests/ublk/kublk.h
> @@ -115,6 +115,7 @@ struct ublk_io {
>  #define UBLKSRV_NEED_FETCH_RQ          (1UL << 0)
>  #define UBLKSRV_NEED_COMMIT_RQ_COMP    (1UL << 1)
>  #define UBLKSRV_IO_FREE                        (1UL << 2)
> +#define UBLKSRV_NEED_GET_DATA           (1UL << 3)
>         unsigned short flags;
>         unsigned short refs;            /* used by target code only */
>
> diff --git a/tools/testing/selftests/ublk/test_generic_07.sh b/tools/testing/selftests/ublk/test_generic_07.sh
> new file mode 100755
> index 000000000000..e3ad36ef7b9a
> --- /dev/null
> +++ b/tools/testing/selftests/ublk/test_generic_07.sh
> @@ -0,0 +1,24 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
> +
> +TID="generic_07"
> +ERR_CODE=0
> +
> +_prep_test "generic" "test UBLK_F_NEED_GET_DATA"
> +
> +_create_backfile 0 256M
> +dev_id=$(_add_ublk_dev -t loop -q 2 -g "${UBLK_BACKFILES[0]}")
> +_check_add_dev $TID $?
> +
> +# run fio over the ublk disk
> +_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M

I thought you were planning to add a _have_program fio check?

Best,
Caleb

> +ERR_CODE=$?
> +if [ "$ERR_CODE" -eq 0 ]; then
> +       _mkfs_mount_test /dev/ublkb"${dev_id}"
> +       ERR_CODE=$?
> +fi
> +
> +_cleanup_test "generic"
> +_show_result $TID $ERR_CODE
> diff --git a/tools/testing/selftests/ublk/test_stress_05.sh b/tools/testing/selftests/ublk/test_stress_05.sh
> index a7071b10224d..88601b48f1cd 100755
> --- a/tools/testing/selftests/ublk/test_stress_05.sh
> +++ b/tools/testing/selftests/ublk/test_stress_05.sh
> @@ -47,15 +47,15 @@ _create_backfile 0 256M
>  _create_backfile 1 256M
>
>  for reissue in $(seq 0 1); do
> -       ublk_io_and_remove 8G -t null -q 4 -g 1 -r 1 -i "$reissue" &
> -       ublk_io_and_remove 256M -t loop -q 4 -g 1 -r 1 -i "$reissue" "${UBLK_BACKFILES[0]}" &
> +       ublk_io_and_remove 8G -t null -q 4 -g -r 1 -i "$reissue" &
> +       ublk_io_and_remove 256M -t loop -q 4 -g -r 1 -i "$reissue" "${UBLK_BACKFILES[0]}" &
>         wait
>  done
>
>  if _have_feature "ZERO_COPY"; then
>         for reissue in $(seq 0 1); do
> -               ublk_io_and_remove 8G -t null -q 4 -g 1 -z -r 1 -i "$reissue" &
> -               ublk_io_and_remove 256M -t loop -q 4 -g 1 -z -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
> +               ublk_io_and_remove 8G -t null -q 4 -g -z -r 1 -i "$reissue" &
> +               ublk_io_and_remove 256M -t loop -q 4 -g -z -r 1 -i "$reissue" "${UBLK_BACKFILES[1]}" &
>                 wait
>         done
>  fi
> --
> 2.47.0
>

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

* Re: [PATCH v6.15 2/3] ublk: decouple zero copy from user copy
  2025-04-27 13:49 ` [PATCH v6.15 2/3] ublk: decouple zero copy from user copy Ming Lei
@ 2025-04-28 16:01   ` Caleb Sander Mateos
  2025-04-29  0:55     ` Ming Lei
  0 siblings, 1 reply; 13+ messages in thread
From: Caleb Sander Mateos @ 2025-04-28 16:01 UTC (permalink / raw)
  To: Ming Lei; +Cc: Jens Axboe, linux-block, Uday Shankar, Keith Busch

On Sun, Apr 27, 2025 at 6:49 AM Ming Lei <ming.lei@redhat.com> wrote:
>
> UBLK_F_USER_COPY and UBLK_F_SUPPORT_ZERO_COPY are two different
> features, and shouldn't be coupled together.
>
> Commit 1f6540e2aabb ("ublk: zc register/unregister bvec") enables
> user copy automatically in case of UBLK_F_SUPPORT_ZERO_COPY, this way
> isn't correct.
>
> So decouple zero copy from user copy, and use independent helper to
> check each one.

I agree this makes sense.

>
> Fixes: 1f6540e2aabb ("ublk: zc register/unregister bvec")
> Signed-off-by: Ming Lei <ming.lei@redhat.com>
> ---
>  drivers/block/ublk_drv.c | 35 +++++++++++++++++++++++------------
>  1 file changed, 23 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> index 40f971a66d3e..0a3a3c64316d 100644
> --- a/drivers/block/ublk_drv.c
> +++ b/drivers/block/ublk_drv.c
> @@ -205,11 +205,6 @@ static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
>  static inline unsigned int ublk_req_build_flags(struct request *req);
>  static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
>                                                    int tag);
> -static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)
> -{
> -       return ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
> -}
> -
>  static inline bool ublk_dev_is_zoned(const struct ublk_device *ub)
>  {
>         return ub->dev_info.flags & UBLK_F_ZONED;
> @@ -609,14 +604,19 @@ static void ublk_apply_params(struct ublk_device *ub)
>                 ublk_dev_param_zoned_apply(ub);
>  }
>
> +static inline bool ublk_support_zero_copy(const struct ublk_queue *ubq)
> +{
> +       return ubq->flags & UBLK_F_SUPPORT_ZERO_COPY;
> +}
> +
>  static inline bool ublk_support_user_copy(const struct ublk_queue *ubq)
>  {
> -       return ubq->flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
> +       return ubq->flags & UBLK_F_USER_COPY;
>  }
>
>  static inline bool ublk_need_map_io(const struct ublk_queue *ubq)
>  {
> -       return !ublk_support_user_copy(ubq);
> +       return !ublk_support_user_copy(ubq) && !ublk_support_zero_copy(ubq);
>  }
>
>  static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
> @@ -624,8 +624,11 @@ static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
>         /*
>          * read()/write() is involved in user copy, so request reference
>          * has to be grabbed
> +        *
> +        * for zero copy, request buffer need to be registered to io_uring
> +        * buffer table, so reference is needed
>          */
> -       return ublk_support_user_copy(ubq);
> +       return ublk_support_user_copy(ubq) || ublk_support_zero_copy(ubq);
>  }
>
>  static inline void ublk_init_req_ref(const struct ublk_queue *ubq,
> @@ -2245,6 +2248,9 @@ static struct request *ublk_check_and_get_req(struct kiocb *iocb,
>         if (!ubq)
>                 return ERR_PTR(-EINVAL);
>
> +       if (!ublk_support_user_copy(ubq))
> +               return ERR_PTR(-EACCES);

This partly overlaps with the existing ublk_need_req_ref() check in
__ublk_check_and_get_req() (although that allows
UBLK_F_SUPPORT_ZERO_COPY too). Can that check be removed now that the
callers explicitly check ublk_support_user_copy() or
ublk_support_zero_copy()?

> +
>         if (tag >= ubq->q_depth)
>                 return ERR_PTR(-EINVAL);
>
> @@ -2783,13 +2789,18 @@ static int ublk_ctrl_add_dev(const struct ublksrv_ctrl_cmd *header)
>         ub->dev_info.flags |= UBLK_F_CMD_IOCTL_ENCODE |
>                 UBLK_F_URING_CMD_COMP_IN_TASK;
>
> -       /* GET_DATA isn't needed any more with USER_COPY */
> -       if (ublk_dev_is_user_copy(ub))
> +       /* GET_DATA isn't needed any more with USER_COPY or ZERO COPY */
> +       if (ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY))
>                 ub->dev_info.flags &= ~UBLK_F_NEED_GET_DATA;
>
> -       /* Zoned storage support requires user copy feature */
> +       /*
> +        * Zoned storage support requires reuse `ublksrv_io_cmd->addr` for
> +        * returning write_append_lba, which is only allowed in case of
> +        * user copy or zero copy

Thanks, this comment is much more helpful.

Best,
Caleb

> +        */
>         if (ublk_dev_is_zoned(ub) &&
> -           (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) || !ublk_dev_is_user_copy(ub))) {
> +           (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) || !(ub->dev_info.flags &
> +            (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY)))) {
>                 ret = -EINVAL;
>                 goto out_free_dev_number;
>         }
> --
> 2.47.0
>

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

* Re: [PATCH v6.15 3/3] ublk: enhance check for register/unregister io buffer command
  2025-04-27 13:49 ` [PATCH v6.15 3/3] ublk: enhance check for register/unregister io buffer command Ming Lei
@ 2025-04-28 16:28   ` Caleb Sander Mateos
  2025-04-29  1:02     ` Ming Lei
  0 siblings, 1 reply; 13+ messages in thread
From: Caleb Sander Mateos @ 2025-04-28 16:28 UTC (permalink / raw)
  To: Ming Lei; +Cc: Jens Axboe, linux-block, Uday Shankar, Keith Busch

On Sun, Apr 27, 2025 at 6:50 AM Ming Lei <ming.lei@redhat.com> wrote:
>
> The simple check of UBLK_IO_FLAG_OWNED_BY_SRV can avoid incorrect
> register/unregister io buffer easily, so check it before calling
> starting to register/un-register io buffer.
>
> Also only allow io buffer register/unregister uring_cmd in case of
> UBLK_F_SUPPORT_ZERO_COPY.
>
> Also mark argument 'ublk_queue *' of ublk_register_io_buf as const.
>
> Fixes: 1f6540e2aabb ("ublk: zc register/unregister bvec")
> Signed-off-by: Ming Lei <ming.lei@redhat.com>
> ---
>  drivers/block/ublk_drv.c | 24 ++++++++++++++++++++----
>  1 file changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> index 0a3a3c64316d..c624d8f653ae 100644
> --- a/drivers/block/ublk_drv.c
> +++ b/drivers/block/ublk_drv.c
> @@ -201,7 +201,7 @@ struct ublk_params_header {
>  static void ublk_stop_dev_unlocked(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,
> -               struct ublk_queue *ubq, int tag, size_t offset);
> +               const struct ublk_queue *ubq, int tag, size_t offset);
>  static inline unsigned int ublk_req_build_flags(struct request *req);
>  static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
>                                                    int tag);
> @@ -1949,13 +1949,20 @@ static void ublk_io_release(void *priv)
>  }
>
>  static int ublk_register_io_buf(struct io_uring_cmd *cmd,
> -                               struct ublk_queue *ubq, unsigned int tag,
> +                               const struct ublk_queue *ubq, unsigned int tag,
>                                 unsigned int index, unsigned int issue_flags)
>  {
>         struct ublk_device *ub = cmd->file->private_data;
> +       const struct ublk_io *io = &ubq->ios[tag];
>         struct request *req;
>         int ret;
>
> +       if (!ublk_support_zero_copy(ubq))
> +               return -EINVAL;
> +
> +       if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
> +               return -EINVAL;

I would still prefer to see this common UBLK_IO_FLAG_OWNED_BY_SRV
check moved to __ublk_ch_uring_cmd() along with the existing flag
checks. Something like this:

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index a183aa7648c3..79ef2580ddcc 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -2055,6 +2055,11 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
                goto out;
        }

+       /* only FETCH_REQ is allowed if io is not OWNED_BY_SRV */
+       if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV) &&
+           _IOC_NR(cmd_op) != UBLK_IO_FETCH_REQ)
+               goto out;
+
        /*
         * ensure that the user issues UBLK_IO_NEED_GET_DATA
         * iff the driver have set the UBLK_IO_FLAG_NEED_GET_DATA.
@@ -2080,10 +2085,6 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
                break;
        case UBLK_IO_COMMIT_AND_FETCH_REQ:
                req = blk_mq_tag_to_rq(ub->tag_set.tags[ub_cmd->q_id], tag);
-
-               if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
-                       goto out;
-
                if (ublk_need_map_io(ubq)) {
                        /*
                         * COMMIT_AND_FETCH_REQ has to provide IO buffer if
@@ -2105,8 +2106,6 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
                ublk_commit_completion(ub, ub_cmd);
                break;
        case UBLK_IO_NEED_GET_DATA:
-               if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
-                       goto out;
                ublk_fill_io_cmd(io, cmd, ub_cmd->addr);
                req = blk_mq_tag_to_rq(ub->tag_set.tags[ub_cmd->q_id], tag);
                ublk_dispatch_req(ubq, req, issue_flags);


> +
>         req = __ublk_check_and_get_req(ub, ubq, tag, 0);
>         if (!req)
>                 return -EINVAL;
> @@ -1971,8 +1978,17 @@ static int ublk_register_io_buf(struct io_uring_cmd *cmd,
>  }
>
>  static int ublk_unregister_io_buf(struct io_uring_cmd *cmd,
> +                                 const struct ublk_queue *ubq, unsigned int tag,
>                                   unsigned int index, unsigned int issue_flags)
>  {
> +       const struct ublk_io *io = &ubq->ios[tag];
> +
> +       if (!ublk_support_zero_copy(ubq))
> +               return -EINVAL;
> +
> +       if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
> +               return -EINVAL;
> +
>         return io_buffer_unregister_bvec(cmd, index, issue_flags);
>  }
>
> @@ -2076,7 +2092,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
>         case UBLK_IO_REGISTER_IO_BUF:
>                 return ublk_register_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
>         case UBLK_IO_UNREGISTER_IO_BUF:
> -               return ublk_unregister_io_buf(cmd, ub_cmd->addr, issue_flags);
> +               return ublk_unregister_io_buf(cmd, ubq, tag, ub_cmd->addr, issue_flags);
>         case UBLK_IO_FETCH_REQ:
>                 ret = ublk_fetch(cmd, ubq, io, ub_cmd->addr);
>                 if (ret)
> @@ -2128,7 +2144,7 @@ static int __ublk_ch_uring_cmd(struct io_uring_cmd *cmd,
>  }
>
>  static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
> -               struct ublk_queue *ubq, int tag, size_t offset)
> +               const struct ublk_queue *ubq, int tag, size_t offset)
>  {
>         struct request *req;
>
> --
> 2.47.0
>

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

* Re: [PATCH v6.15 1/3] selftests: ublk: fix UBLK_F_NEED_GET_DATA
  2025-04-28 15:51   ` Caleb Sander Mateos
@ 2025-04-29  0:53     ` Ming Lei
  0 siblings, 0 replies; 13+ messages in thread
From: Ming Lei @ 2025-04-29  0:53 UTC (permalink / raw)
  To: Caleb Sander Mateos; +Cc: Jens Axboe, linux-block, Uday Shankar, Keith Busch

On Mon, Apr 28, 2025 at 08:51:03AM -0700, Caleb Sander Mateos wrote:
> On Sun, Apr 27, 2025 at 6:49 AM Ming Lei <ming.lei@redhat.com> wrote:
> >
> > Commit 57e13a2e8cd2 ("selftests: ublk: support user recovery") starts to
> > support UBLK_F_NEED_GET_DATA for covering recovery feature, however the
> > ublk utility implementation isn't done correctly.
> >
> > Fix it by supporting UBLK_F_NEED_GET_DATA correctly.
> >
> > Also add test generic_07 for covering UBLK_F_NEED_GET_DATA.
> >
> > Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
> > Fixes: 57e13a2e8cd2 ("selftests: ublk: support user recovery")
> > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > ---
> >  tools/testing/selftests/ublk/Makefile         |  1 +
> >  tools/testing/selftests/ublk/kublk.c          | 20 ++++++++++------
> >  tools/testing/selftests/ublk/kublk.h          |  1 +
> >  .../testing/selftests/ublk/test_generic_07.sh | 24 +++++++++++++++++++
> >  .../testing/selftests/ublk/test_stress_05.sh  |  8 +++----
> >  5 files changed, 43 insertions(+), 11 deletions(-)
> >  create mode 100755 tools/testing/selftests/ublk/test_generic_07.sh
> >
> > diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile
> > index ec4624a283bc..f34ac0bac696 100644
> > --- a/tools/testing/selftests/ublk/Makefile
> > +++ b/tools/testing/selftests/ublk/Makefile
> > @@ -9,6 +9,7 @@ TEST_PROGS += test_generic_03.sh
> >  TEST_PROGS += test_generic_04.sh
> >  TEST_PROGS += test_generic_05.sh
> >  TEST_PROGS += test_generic_06.sh
> > +TEST_PROGS += test_generic_07.sh
> >
> >  TEST_PROGS += test_null_01.sh
> >  TEST_PROGS += test_null_02.sh
> > diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
> > index e57a1486bb48..3afd45d7f989 100644
> > --- a/tools/testing/selftests/ublk/kublk.c
> > +++ b/tools/testing/selftests/ublk/kublk.c
> > @@ -536,12 +536,17 @@ int ublk_queue_io_cmd(struct ublk_queue *q, struct ublk_io *io, unsigned tag)
> >         if (!(io->flags & UBLKSRV_IO_FREE))
> >                 return 0;
> >
> > -       /* we issue because we need either fetching or committing */
> > +       /*
> > +        * we issue because we need either fetching or committing or
> > +        * getting data
> > +        */
> >         if (!(io->flags &
> > -               (UBLKSRV_NEED_FETCH_RQ | UBLKSRV_NEED_COMMIT_RQ_COMP)))
> > +               (UBLKSRV_NEED_FETCH_RQ | UBLKSRV_NEED_COMMIT_RQ_COMP | UBLKSRV_NEED_GET_DATA)))
> >                 return 0;
> >
> > -       if (io->flags & UBLKSRV_NEED_COMMIT_RQ_COMP)
> > +       if (io->flags & UBLKSRV_NEED_GET_DATA)
> > +               cmd_op = UBLK_U_IO_NEED_GET_DATA;
> > +       else if (io->flags & UBLKSRV_NEED_COMMIT_RQ_COMP)
> >                 cmd_op = UBLK_U_IO_COMMIT_AND_FETCH_REQ;
> >         else if (io->flags & UBLKSRV_NEED_FETCH_RQ)
> >                 cmd_op = UBLK_U_IO_FETCH_REQ;
> > @@ -658,6 +663,9 @@ static void ublk_handle_cqe(struct io_uring *r,
> >                 assert(tag < q->q_depth);
> >                 if (q->tgt_ops->queue_io)
> >                         q->tgt_ops->queue_io(q, tag);
> > +       } else if (cqe->res == UBLK_IO_RES_NEED_GET_DATA) {
> > +               io->flags |= UBLKSRV_NEED_GET_DATA | UBLKSRV_IO_FREE;
> > +               ublk_queue_io_cmd(q, io, tag);
> >         } else {
> >                 /*
> >                  * COMMIT_REQ will be completed immediately since no fetching
> > @@ -1313,7 +1321,7 @@ int main(int argc, char *argv[])
> >
> >         opterr = 0;
> >         optind = 2;
> > -       while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:az",
> > +       while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:gaz",
> >                                   longopts, &option_idx)) != -1) {
> >                 switch (opt) {
> >                 case 'a':
> > @@ -1351,9 +1359,7 @@ int main(int argc, char *argv[])
> >                                 ctx.flags |= UBLK_F_USER_RECOVERY | UBLK_F_USER_RECOVERY_REISSUE;
> >                         break;
> >                 case 'g':
> > -                       value = strtol(optarg, NULL, 10);
> > -                       if (value)
> > -                               ctx.flags |= UBLK_F_NEED_GET_DATA;
> > +                       ctx.flags |= UBLK_F_NEED_GET_DATA;
> 
> The help text in __cmd_create_help() should be updated accordingly.

Good catch!

> 
> >                         break;
> >                 case 0:
> >                         if (!strcmp(longopts[option_idx].name, "debug_mask"))
> > diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h
> > index 918db5cd633f..44ee1e4ac55b 100644
> > --- a/tools/testing/selftests/ublk/kublk.h
> > +++ b/tools/testing/selftests/ublk/kublk.h
> > @@ -115,6 +115,7 @@ struct ublk_io {
> >  #define UBLKSRV_NEED_FETCH_RQ          (1UL << 0)
> >  #define UBLKSRV_NEED_COMMIT_RQ_COMP    (1UL << 1)
> >  #define UBLKSRV_IO_FREE                        (1UL << 2)
> > +#define UBLKSRV_NEED_GET_DATA           (1UL << 3)
> >         unsigned short flags;
> >         unsigned short refs;            /* used by target code only */
> >
> > diff --git a/tools/testing/selftests/ublk/test_generic_07.sh b/tools/testing/selftests/ublk/test_generic_07.sh
> > new file mode 100755
> > index 000000000000..e3ad36ef7b9a
> > --- /dev/null
> > +++ b/tools/testing/selftests/ublk/test_generic_07.sh
> > @@ -0,0 +1,24 @@
> > +#!/bin/bash
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
> > +
> > +TID="generic_07"
> > +ERR_CODE=0
> > +
> > +_prep_test "generic" "test UBLK_F_NEED_GET_DATA"
> > +
> > +_create_backfile 0 256M
> > +dev_id=$(_add_ublk_dev -t loop -q 2 -g "${UBLK_BACKFILES[0]}")
> > +_check_add_dev $TID $?
> > +
> > +# run fio over the ublk disk
> > +_run_fio_verify_io --filename=/dev/ublkb"${dev_id}" --size=256M
> 
> I thought you were planning to add a _have_program fio check?

Indeed, don't know how the check wasn't added, :-(


thanks,
Ming


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

* Re: [PATCH v6.15 2/3] ublk: decouple zero copy from user copy
  2025-04-28 16:01   ` Caleb Sander Mateos
@ 2025-04-29  0:55     ` Ming Lei
  2025-04-29  1:36       ` Ming Lei
  0 siblings, 1 reply; 13+ messages in thread
From: Ming Lei @ 2025-04-29  0:55 UTC (permalink / raw)
  To: Caleb Sander Mateos; +Cc: Jens Axboe, linux-block, Uday Shankar, Keith Busch

On Mon, Apr 28, 2025 at 09:01:04AM -0700, Caleb Sander Mateos wrote:
> On Sun, Apr 27, 2025 at 6:49 AM Ming Lei <ming.lei@redhat.com> wrote:
> >
> > UBLK_F_USER_COPY and UBLK_F_SUPPORT_ZERO_COPY are two different
> > features, and shouldn't be coupled together.
> >
> > Commit 1f6540e2aabb ("ublk: zc register/unregister bvec") enables
> > user copy automatically in case of UBLK_F_SUPPORT_ZERO_COPY, this way
> > isn't correct.
> >
> > So decouple zero copy from user copy, and use independent helper to
> > check each one.
> 
> I agree this makes sense.
> 
> >
> > Fixes: 1f6540e2aabb ("ublk: zc register/unregister bvec")
> > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > ---
> >  drivers/block/ublk_drv.c | 35 +++++++++++++++++++++++------------
> >  1 file changed, 23 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> > index 40f971a66d3e..0a3a3c64316d 100644
> > --- a/drivers/block/ublk_drv.c
> > +++ b/drivers/block/ublk_drv.c
> > @@ -205,11 +205,6 @@ static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
> >  static inline unsigned int ublk_req_build_flags(struct request *req);
> >  static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
> >                                                    int tag);
> > -static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)
> > -{
> > -       return ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
> > -}
> > -
> >  static inline bool ublk_dev_is_zoned(const struct ublk_device *ub)
> >  {
> >         return ub->dev_info.flags & UBLK_F_ZONED;
> > @@ -609,14 +604,19 @@ static void ublk_apply_params(struct ublk_device *ub)
> >                 ublk_dev_param_zoned_apply(ub);
> >  }
> >
> > +static inline bool ublk_support_zero_copy(const struct ublk_queue *ubq)
> > +{
> > +       return ubq->flags & UBLK_F_SUPPORT_ZERO_COPY;
> > +}
> > +
> >  static inline bool ublk_support_user_copy(const struct ublk_queue *ubq)
> >  {
> > -       return ubq->flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
> > +       return ubq->flags & UBLK_F_USER_COPY;
> >  }
> >
> >  static inline bool ublk_need_map_io(const struct ublk_queue *ubq)
> >  {
> > -       return !ublk_support_user_copy(ubq);
> > +       return !ublk_support_user_copy(ubq) && !ublk_support_zero_copy(ubq);
> >  }
> >
> >  static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
> > @@ -624,8 +624,11 @@ static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
> >         /*
> >          * read()/write() is involved in user copy, so request reference
> >          * has to be grabbed
> > +        *
> > +        * for zero copy, request buffer need to be registered to io_uring
> > +        * buffer table, so reference is needed
> >          */
> > -       return ublk_support_user_copy(ubq);
> > +       return ublk_support_user_copy(ubq) || ublk_support_zero_copy(ubq);
> >  }
> >
> >  static inline void ublk_init_req_ref(const struct ublk_queue *ubq,
> > @@ -2245,6 +2248,9 @@ static struct request *ublk_check_and_get_req(struct kiocb *iocb,
> >         if (!ubq)
> >                 return ERR_PTR(-EINVAL);
> >
> > +       if (!ublk_support_user_copy(ubq))
> > +               return ERR_PTR(-EACCES);
> 
> This partly overlaps with the existing ublk_need_req_ref() check in
> __ublk_check_and_get_req() (although that allows
> UBLK_F_SUPPORT_ZERO_COPY too). Can that check be removed now that the
> callers explicitly check ublk_support_user_copy() or
> ublk_support_zero_copy()?

Yeah, it can be removed.


Thanks, 
Ming


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

* Re: [PATCH v6.15 3/3] ublk: enhance check for register/unregister io buffer command
  2025-04-28 16:28   ` Caleb Sander Mateos
@ 2025-04-29  1:02     ` Ming Lei
  2025-04-29  1:03       ` Caleb Sander Mateos
  0 siblings, 1 reply; 13+ messages in thread
From: Ming Lei @ 2025-04-29  1:02 UTC (permalink / raw)
  To: Caleb Sander Mateos; +Cc: Jens Axboe, linux-block, Uday Shankar, Keith Busch

On Mon, Apr 28, 2025 at 09:28:07AM -0700, Caleb Sander Mateos wrote:
> On Sun, Apr 27, 2025 at 6:50 AM Ming Lei <ming.lei@redhat.com> wrote:
> >
> > The simple check of UBLK_IO_FLAG_OWNED_BY_SRV can avoid incorrect
> > register/unregister io buffer easily, so check it before calling
> > starting to register/un-register io buffer.
> >
> > Also only allow io buffer register/unregister uring_cmd in case of
> > UBLK_F_SUPPORT_ZERO_COPY.
> >
> > Also mark argument 'ublk_queue *' of ublk_register_io_buf as const.
> >
> > Fixes: 1f6540e2aabb ("ublk: zc register/unregister bvec")
> > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > ---
> >  drivers/block/ublk_drv.c | 24 ++++++++++++++++++++----
> >  1 file changed, 20 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> > index 0a3a3c64316d..c624d8f653ae 100644
> > --- a/drivers/block/ublk_drv.c
> > +++ b/drivers/block/ublk_drv.c
> > @@ -201,7 +201,7 @@ struct ublk_params_header {
> >  static void ublk_stop_dev_unlocked(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,
> > -               struct ublk_queue *ubq, int tag, size_t offset);
> > +               const struct ublk_queue *ubq, int tag, size_t offset);
> >  static inline unsigned int ublk_req_build_flags(struct request *req);
> >  static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
> >                                                    int tag);
> > @@ -1949,13 +1949,20 @@ static void ublk_io_release(void *priv)
> >  }
> >
> >  static int ublk_register_io_buf(struct io_uring_cmd *cmd,
> > -                               struct ublk_queue *ubq, unsigned int tag,
> > +                               const struct ublk_queue *ubq, unsigned int tag,
> >                                 unsigned int index, unsigned int issue_flags)
> >  {
> >         struct ublk_device *ub = cmd->file->private_data;
> > +       const struct ublk_io *io = &ubq->ios[tag];
> >         struct request *req;
> >         int ret;
> >
> > +       if (!ublk_support_zero_copy(ubq))
> > +               return -EINVAL;
> > +
> > +       if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
> > +               return -EINVAL;
> 
> I would still prefer to see this common UBLK_IO_FLAG_OWNED_BY_SRV
> check moved to __ublk_ch_uring_cmd() along with the existing flag
> checks. Something like this:

This way mixes bug fix with cleanup.

We are close to v6.15-rc5, and bug fix should keep simple for minimizing
regression.

But it is fine to make it one cleanup aiming at v6.16.


thanks,
Ming


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

* Re: [PATCH v6.15 3/3] ublk: enhance check for register/unregister io buffer command
  2025-04-29  1:02     ` Ming Lei
@ 2025-04-29  1:03       ` Caleb Sander Mateos
  0 siblings, 0 replies; 13+ messages in thread
From: Caleb Sander Mateos @ 2025-04-29  1:03 UTC (permalink / raw)
  To: Ming Lei; +Cc: Jens Axboe, linux-block, Uday Shankar, Keith Busch

On Mon, Apr 28, 2025 at 6:02 PM Ming Lei <ming.lei@redhat.com> wrote:
>
> On Mon, Apr 28, 2025 at 09:28:07AM -0700, Caleb Sander Mateos wrote:
> > On Sun, Apr 27, 2025 at 6:50 AM Ming Lei <ming.lei@redhat.com> wrote:
> > >
> > > The simple check of UBLK_IO_FLAG_OWNED_BY_SRV can avoid incorrect
> > > register/unregister io buffer easily, so check it before calling
> > > starting to register/un-register io buffer.
> > >
> > > Also only allow io buffer register/unregister uring_cmd in case of
> > > UBLK_F_SUPPORT_ZERO_COPY.
> > >
> > > Also mark argument 'ublk_queue *' of ublk_register_io_buf as const.
> > >
> > > Fixes: 1f6540e2aabb ("ublk: zc register/unregister bvec")
> > > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > > ---
> > >  drivers/block/ublk_drv.c | 24 ++++++++++++++++++++----
> > >  1 file changed, 20 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> > > index 0a3a3c64316d..c624d8f653ae 100644
> > > --- a/drivers/block/ublk_drv.c
> > > +++ b/drivers/block/ublk_drv.c
> > > @@ -201,7 +201,7 @@ struct ublk_params_header {
> > >  static void ublk_stop_dev_unlocked(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,
> > > -               struct ublk_queue *ubq, int tag, size_t offset);
> > > +               const struct ublk_queue *ubq, int tag, size_t offset);
> > >  static inline unsigned int ublk_req_build_flags(struct request *req);
> > >  static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
> > >                                                    int tag);
> > > @@ -1949,13 +1949,20 @@ static void ublk_io_release(void *priv)
> > >  }
> > >
> > >  static int ublk_register_io_buf(struct io_uring_cmd *cmd,
> > > -                               struct ublk_queue *ubq, unsigned int tag,
> > > +                               const struct ublk_queue *ubq, unsigned int tag,
> > >                                 unsigned int index, unsigned int issue_flags)
> > >  {
> > >         struct ublk_device *ub = cmd->file->private_data;
> > > +       const struct ublk_io *io = &ubq->ios[tag];
> > >         struct request *req;
> > >         int ret;
> > >
> > > +       if (!ublk_support_zero_copy(ubq))
> > > +               return -EINVAL;
> > > +
> > > +       if (!(io->flags & UBLK_IO_FLAG_OWNED_BY_SRV))
> > > +               return -EINVAL;
> >
> > I would still prefer to see this common UBLK_IO_FLAG_OWNED_BY_SRV
> > check moved to __ublk_ch_uring_cmd() along with the existing flag
> > checks. Something like this:
>
> This way mixes bug fix with cleanup.
>
> We are close to v6.15-rc5, and bug fix should keep simple for minimizing
> regression.
>
> But it is fine to make it one cleanup aiming at v6.16.

Okay, I can send out this cleanup for 6.16. In that case,

Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>

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

* Re: [PATCH v6.15 2/3] ublk: decouple zero copy from user copy
  2025-04-29  0:55     ` Ming Lei
@ 2025-04-29  1:36       ` Ming Lei
  2025-04-29  1:38         ` Caleb Sander Mateos
  0 siblings, 1 reply; 13+ messages in thread
From: Ming Lei @ 2025-04-29  1:36 UTC (permalink / raw)
  To: Caleb Sander Mateos; +Cc: Jens Axboe, linux-block, Uday Shankar, Keith Busch

On Tue, Apr 29, 2025 at 08:55:48AM +0800, Ming Lei wrote:
> On Mon, Apr 28, 2025 at 09:01:04AM -0700, Caleb Sander Mateos wrote:
> > On Sun, Apr 27, 2025 at 6:49 AM Ming Lei <ming.lei@redhat.com> wrote:
> > >
> > > UBLK_F_USER_COPY and UBLK_F_SUPPORT_ZERO_COPY are two different
> > > features, and shouldn't be coupled together.
> > >
> > > Commit 1f6540e2aabb ("ublk: zc register/unregister bvec") enables
> > > user copy automatically in case of UBLK_F_SUPPORT_ZERO_COPY, this way
> > > isn't correct.
> > >
> > > So decouple zero copy from user copy, and use independent helper to
> > > check each one.
> > 
> > I agree this makes sense.
> > 
> > >
> > > Fixes: 1f6540e2aabb ("ublk: zc register/unregister bvec")
> > > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > > ---
> > >  drivers/block/ublk_drv.c | 35 +++++++++++++++++++++++------------
> > >  1 file changed, 23 insertions(+), 12 deletions(-)
> > >
> > > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> > > index 40f971a66d3e..0a3a3c64316d 100644
> > > --- a/drivers/block/ublk_drv.c
> > > +++ b/drivers/block/ublk_drv.c
> > > @@ -205,11 +205,6 @@ static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
> > >  static inline unsigned int ublk_req_build_flags(struct request *req);
> > >  static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
> > >                                                    int tag);
> > > -static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)
> > > -{
> > > -       return ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
> > > -}
> > > -
> > >  static inline bool ublk_dev_is_zoned(const struct ublk_device *ub)
> > >  {
> > >         return ub->dev_info.flags & UBLK_F_ZONED;
> > > @@ -609,14 +604,19 @@ static void ublk_apply_params(struct ublk_device *ub)
> > >                 ublk_dev_param_zoned_apply(ub);
> > >  }
> > >
> > > +static inline bool ublk_support_zero_copy(const struct ublk_queue *ubq)
> > > +{
> > > +       return ubq->flags & UBLK_F_SUPPORT_ZERO_COPY;
> > > +}
> > > +
> > >  static inline bool ublk_support_user_copy(const struct ublk_queue *ubq)
> > >  {
> > > -       return ubq->flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
> > > +       return ubq->flags & UBLK_F_USER_COPY;
> > >  }
> > >
> > >  static inline bool ublk_need_map_io(const struct ublk_queue *ubq)
> > >  {
> > > -       return !ublk_support_user_copy(ubq);
> > > +       return !ublk_support_user_copy(ubq) && !ublk_support_zero_copy(ubq);
> > >  }
> > >
> > >  static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
> > > @@ -624,8 +624,11 @@ static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
> > >         /*
> > >          * read()/write() is involved in user copy, so request reference
> > >          * has to be grabbed
> > > +        *
> > > +        * for zero copy, request buffer need to be registered to io_uring
> > > +        * buffer table, so reference is needed
> > >          */
> > > -       return ublk_support_user_copy(ubq);
> > > +       return ublk_support_user_copy(ubq) || ublk_support_zero_copy(ubq);
> > >  }
> > >
> > >  static inline void ublk_init_req_ref(const struct ublk_queue *ubq,
> > > @@ -2245,6 +2248,9 @@ static struct request *ublk_check_and_get_req(struct kiocb *iocb,
> > >         if (!ubq)
> > >                 return ERR_PTR(-EINVAL);
> > >
> > > +       if (!ublk_support_user_copy(ubq))
> > > +               return ERR_PTR(-EACCES);
> > 
> > This partly overlaps with the existing ublk_need_req_ref() check in
> > __ublk_check_and_get_req() (although that allows
> > UBLK_F_SUPPORT_ZERO_COPY too). Can that check be removed now that the
> > callers explicitly check ublk_support_user_copy() or
> > ublk_support_zero_copy()?
> 
> Yeah, it can be removed.

Actually the removal can only be done after the 3rd patch is applied with
zero copy check is added.



Thanks,
Ming


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

* Re: [PATCH v6.15 2/3] ublk: decouple zero copy from user copy
  2025-04-29  1:36       ` Ming Lei
@ 2025-04-29  1:38         ` Caleb Sander Mateos
  0 siblings, 0 replies; 13+ messages in thread
From: Caleb Sander Mateos @ 2025-04-29  1:38 UTC (permalink / raw)
  To: Ming Lei; +Cc: Jens Axboe, linux-block, Uday Shankar, Keith Busch

On Mon, Apr 28, 2025 at 6:36 PM Ming Lei <ming.lei@redhat.com> wrote:
>
> On Tue, Apr 29, 2025 at 08:55:48AM +0800, Ming Lei wrote:
> > On Mon, Apr 28, 2025 at 09:01:04AM -0700, Caleb Sander Mateos wrote:
> > > On Sun, Apr 27, 2025 at 6:49 AM Ming Lei <ming.lei@redhat.com> wrote:
> > > >
> > > > UBLK_F_USER_COPY and UBLK_F_SUPPORT_ZERO_COPY are two different
> > > > features, and shouldn't be coupled together.
> > > >
> > > > Commit 1f6540e2aabb ("ublk: zc register/unregister bvec") enables
> > > > user copy automatically in case of UBLK_F_SUPPORT_ZERO_COPY, this way
> > > > isn't correct.
> > > >
> > > > So decouple zero copy from user copy, and use independent helper to
> > > > check each one.
> > >
> > > I agree this makes sense.
> > >
> > > >
> > > > Fixes: 1f6540e2aabb ("ublk: zc register/unregister bvec")
> > > > Signed-off-by: Ming Lei <ming.lei@redhat.com>
> > > > ---
> > > >  drivers/block/ublk_drv.c | 35 +++++++++++++++++++++++------------
> > > >  1 file changed, 23 insertions(+), 12 deletions(-)
> > > >
> > > > diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> > > > index 40f971a66d3e..0a3a3c64316d 100644
> > > > --- a/drivers/block/ublk_drv.c
> > > > +++ b/drivers/block/ublk_drv.c
> > > > @@ -205,11 +205,6 @@ static inline struct request *__ublk_check_and_get_req(struct ublk_device *ub,
> > > >  static inline unsigned int ublk_req_build_flags(struct request *req);
> > > >  static inline struct ublksrv_io_desc *ublk_get_iod(struct ublk_queue *ubq,
> > > >                                                    int tag);
> > > > -static inline bool ublk_dev_is_user_copy(const struct ublk_device *ub)
> > > > -{
> > > > -       return ub->dev_info.flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
> > > > -}
> > > > -
> > > >  static inline bool ublk_dev_is_zoned(const struct ublk_device *ub)
> > > >  {
> > > >         return ub->dev_info.flags & UBLK_F_ZONED;
> > > > @@ -609,14 +604,19 @@ static void ublk_apply_params(struct ublk_device *ub)
> > > >                 ublk_dev_param_zoned_apply(ub);
> > > >  }
> > > >
> > > > +static inline bool ublk_support_zero_copy(const struct ublk_queue *ubq)
> > > > +{
> > > > +       return ubq->flags & UBLK_F_SUPPORT_ZERO_COPY;
> > > > +}
> > > > +
> > > >  static inline bool ublk_support_user_copy(const struct ublk_queue *ubq)
> > > >  {
> > > > -       return ubq->flags & (UBLK_F_USER_COPY | UBLK_F_SUPPORT_ZERO_COPY);
> > > > +       return ubq->flags & UBLK_F_USER_COPY;
> > > >  }
> > > >
> > > >  static inline bool ublk_need_map_io(const struct ublk_queue *ubq)
> > > >  {
> > > > -       return !ublk_support_user_copy(ubq);
> > > > +       return !ublk_support_user_copy(ubq) && !ublk_support_zero_copy(ubq);
> > > >  }
> > > >
> > > >  static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
> > > > @@ -624,8 +624,11 @@ static inline bool ublk_need_req_ref(const struct ublk_queue *ubq)
> > > >         /*
> > > >          * read()/write() is involved in user copy, so request reference
> > > >          * has to be grabbed
> > > > +        *
> > > > +        * for zero copy, request buffer need to be registered to io_uring
> > > > +        * buffer table, so reference is needed
> > > >          */
> > > > -       return ublk_support_user_copy(ubq);
> > > > +       return ublk_support_user_copy(ubq) || ublk_support_zero_copy(ubq);
> > > >  }
> > > >
> > > >  static inline void ublk_init_req_ref(const struct ublk_queue *ubq,
> > > > @@ -2245,6 +2248,9 @@ static struct request *ublk_check_and_get_req(struct kiocb *iocb,
> > > >         if (!ubq)
> > > >                 return ERR_PTR(-EINVAL);
> > > >
> > > > +       if (!ublk_support_user_copy(ubq))
> > > > +               return ERR_PTR(-EACCES);
> > >
> > > This partly overlaps with the existing ublk_need_req_ref() check in
> > > __ublk_check_and_get_req() (although that allows
> > > UBLK_F_SUPPORT_ZERO_COPY too). Can that check be removed now that the
> > > callers explicitly check ublk_support_user_copy() or
> > > ublk_support_zero_copy()?
> >
> > Yeah, it can be removed.
>
> Actually the removal can only be done after the 3rd patch is applied with
> zero copy check is added.

Right, I just meant it can be removed in this series.

Thanks,
Caleb

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

end of thread, other threads:[~2025-04-29  1:39 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-27 13:49 [PATCH v6.15 0/3] ublk: one selftest fix and two zero copy fixes Ming Lei
2025-04-27 13:49 ` [PATCH v6.15 1/3] selftests: ublk: fix UBLK_F_NEED_GET_DATA Ming Lei
2025-04-28 15:51   ` Caleb Sander Mateos
2025-04-29  0:53     ` Ming Lei
2025-04-27 13:49 ` [PATCH v6.15 2/3] ublk: decouple zero copy from user copy Ming Lei
2025-04-28 16:01   ` Caleb Sander Mateos
2025-04-29  0:55     ` Ming Lei
2025-04-29  1:36       ` Ming Lei
2025-04-29  1:38         ` Caleb Sander Mateos
2025-04-27 13:49 ` [PATCH v6.15 3/3] ublk: enhance check for register/unregister io buffer command Ming Lei
2025-04-28 16:28   ` Caleb Sander Mateos
2025-04-29  1:02     ` Ming Lei
2025-04-29  1:03       ` Caleb Sander Mateos

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