Linux block layer
 help / color / mirror / Atom feed
* [PATCH v2 0/2] ublk: fix auto buf reg ordering around uring_cmd
@ 2026-07-30  1:09 Yang Xiuwei
  2026-07-30  1:09 ` [PATCH v2 1/2] ublk: validate auto buf reg before taking uring_cmd Yang Xiuwei
  2026-07-30  1:09 ` [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit Yang Xiuwei
  0 siblings, 2 replies; 7+ messages in thread
From: Yang Xiuwei @ 2026-07-30  1:09 UTC (permalink / raw)
  To: Ming Lei, Jens Axboe; +Cc: linux-block, Caleb Sander Mateos, Yang Xiuwei

Two UBLK_F_AUTO_BUF_REG ordering fixes.

Patch 1: invalid auto_buf in sqe->addr can fail after ublk_fill_io_cmd()
has already set UBLK_IO_FLAG_ACTIVE. Split validate/apply so the check
has no side effects, then take the uring_cmd and store the validated
buffer.

Patch 2: batch commit wrote the new auto_buf into io->buf before
ublk_clear_auto_buf_reg(), so unregister could target the new index and
leave the old registered buffer behind. Clear first, then update
io->buf.

Changes in v2:
- patch 1: validate before __ublk_fetch()/fill; apply is infallible
  (per Caleb's review)
- add patch 2 for the batch commit clear/store order

Tested: 
ublk selftests generic_08/09, batch_01..03, stress_08;
liburing uring_cmd_ublk.t

v1: https://lore.kernel.org/linux-block/20260724100327.43482-1-yangxiuwei@kylinos.cn/

Yang Xiuwei (2):
  ublk: validate auto buf reg before taking uring_cmd
  ublk: clear auto buf reg before updating io->buf in batch commit

 drivers/block/ublk_drv.c | 76 +++++++++++++++++++++-------------------
 1 file changed, 39 insertions(+), 37 deletions(-)

-- 
2.25.1


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

* [PATCH v2 1/2] ublk: validate auto buf reg before taking uring_cmd
  2026-07-30  1:09 [PATCH v2 0/2] ublk: fix auto buf reg ordering around uring_cmd Yang Xiuwei
@ 2026-07-30  1:09 ` Yang Xiuwei
  2026-07-31 16:10   ` Ming Lei
  2026-07-30  1:09 ` [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit Yang Xiuwei
  1 sibling, 1 reply; 7+ messages in thread
From: Yang Xiuwei @ 2026-07-30  1:09 UTC (permalink / raw)
  To: Ming Lei, Jens Axboe; +Cc: linux-block, Caleb Sander Mateos, Yang Xiuwei

With UBLK_F_AUTO_BUF_REG, invalid sqe->addr can fail after
ublk_fill_io_cmd() has set UBLK_IO_FLAG_ACTIVE. The uring_cmd is
completed while the tag stays active, which can hang teardown.

Split validation from buffer apply so the check has no side effects,
then take the uring_cmd and store the already-validated buffer. Apply
the same order in FETCH so io->buf is not written before __ublk_fetch()
state checks.

Fixes: 52460dda3a77 ("ublk: move auto buffer register handling into one dedicated helper")
Suggested-by: Caleb Sander Mateos <csander@purestorage.com>
Signed-off-by: Yang Xiuwei <yangxiuwei@kylinos.cn>
---
 drivers/block/ublk_drv.c | 74 +++++++++++++++++++++-------------------
 1 file changed, 38 insertions(+), 36 deletions(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 4ca6ec738c93..041bd3ea023f 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -3075,18 +3075,19 @@ static inline int ublk_check_cmd_op(u32 cmd_op)
 	return 0;
 }
 
-static inline int ublk_set_auto_buf_reg(struct ublk_io *io, struct io_uring_cmd *cmd)
+/* Must run before ublk_fill_io_cmd() / __ublk_fetch(). */
+static inline int ublk_validate_io_buf(const struct ublk_device *ub,
+				       struct io_uring_cmd *cmd,
+				       struct ublk_auto_buf_reg *buf)
 {
-	struct ublk_auto_buf_reg buf;
-
-	buf = ublk_sqe_addr_to_auto_buf_reg(READ_ONCE(cmd->sqe->addr));
+	if (!ublk_dev_support_auto_buf_reg(ub))
+		return 0;
 
-	if (buf.reserved0 || buf.reserved1)
+	*buf = ublk_sqe_addr_to_auto_buf_reg(READ_ONCE(cmd->sqe->addr));
+	if (buf->reserved0 || buf->reserved1)
 		return -EINVAL;
-
-	if (buf.flags & ~UBLK_AUTO_BUF_REG_F_MASK)
+	if (buf->flags & ~UBLK_AUTO_BUF_REG_F_MASK)
 		return -EINVAL;
-	io->buf.auto_reg = buf;
 	return 0;
 }
 
@@ -3107,17 +3108,25 @@ static void ublk_clear_auto_buf_reg(struct ublk_io *io,
 		 * responsibility for unregistering the buffer, otherwise
 		 * this ublk request gets stuck.
 		 */
-		if (io->buf_ctx_handle == io_uring_cmd_ctx_handle(cmd))
+		if (buf_idx &&
+		    io->buf_ctx_handle == io_uring_cmd_ctx_handle(cmd))
 			*buf_idx = io->buf.auto_reg.index;
 	}
 }
 
-static int ublk_handle_auto_buf_reg(struct ublk_io *io,
-				    struct io_uring_cmd *cmd,
-				    u16 *buf_idx)
+static inline void ublk_apply_io_buf(const struct ublk_device *ub,
+				     struct ublk_io *io,
+				     struct io_uring_cmd *cmd,
+				     unsigned long buf_addr,
+				     const struct ublk_auto_buf_reg *auto_buf,
+				     u16 *buf_idx)
 {
-	ublk_clear_auto_buf_reg(io, cmd, buf_idx);
-	return ublk_set_auto_buf_reg(io, cmd);
+	if (ublk_dev_support_auto_buf_reg(ub)) {
+		ublk_clear_auto_buf_reg(io, cmd, buf_idx);
+		io->buf.auto_reg = *auto_buf;
+	} else {
+		io->buf.addr = buf_addr;
+	}
 }
 
 /* Once we return, `io->req` can't be used any more */
@@ -3134,18 +3143,6 @@ ublk_fill_io_cmd(struct ublk_io *io, struct io_uring_cmd *cmd)
 	return req;
 }
 
-static inline int
-ublk_config_io_buf(const struct ublk_device *ub, struct ublk_io *io,
-		   struct io_uring_cmd *cmd, unsigned long buf_addr,
-		   u16 *buf_idx)
-{
-	if (ublk_dev_support_auto_buf_reg(ub))
-		return ublk_handle_auto_buf_reg(io, cmd, buf_idx);
-
-	io->buf.addr = buf_addr;
-	return 0;
-}
-
 static inline void ublk_prep_cancel(struct io_uring_cmd *cmd,
 				    unsigned int issue_flags,
 				    struct ublk_queue *ubq, unsigned int tag)
@@ -3286,6 +3283,7 @@ static int __ublk_fetch(struct io_uring_cmd *cmd, struct ublk_device *ub,
 static int ublk_fetch(struct io_uring_cmd *cmd, struct ublk_device *ub,
 		      struct ublk_io *io, __u64 buf_addr, u16 q_id)
 {
+	struct ublk_auto_buf_reg auto_buf;
 	int ret;
 
 	/*
@@ -3294,11 +3292,13 @@ static int ublk_fetch(struct io_uring_cmd *cmd, struct ublk_device *ub,
 	 * FETCH, so it is fine even for IO_URING_F_NONBLOCK.
 	 */
 	mutex_lock(&ub->mutex);
-	ret = __ublk_fetch(cmd, ub, io, q_id);
-	if (!ret)
-		ret = ublk_config_io_buf(ub, io, cmd, buf_addr, NULL);
+	ret = ublk_validate_io_buf(ub, cmd, &auto_buf);
 	if (!ret)
+		ret = __ublk_fetch(cmd, ub, io, q_id);
+	if (!ret) {
+		ublk_apply_io_buf(ub, io, cmd, buf_addr, &auto_buf, NULL);
 		ublk_mark_io_ready(ub, q_id, io);
+	}
 	mutex_unlock(&ub->mutex);
 	return ret;
 }
@@ -3441,13 +3441,18 @@ static int ublk_ch_uring_cmd_local(struct io_uring_cmd *cmd,
 	case UBLK_IO_REGISTER_IO_BUF:
 		return ublk_daemon_register_io_buf(cmd, ub, q_id, tag, io, addr,
 						   issue_flags);
-	case UBLK_IO_COMMIT_AND_FETCH_REQ:
+	case UBLK_IO_COMMIT_AND_FETCH_REQ: {
+		struct ublk_auto_buf_reg auto_buf;
+
 		ret = ublk_check_commit_and_fetch(ub, io, addr);
+		if (ret)
+			goto out;
+		ret = ublk_validate_io_buf(ub, cmd, &auto_buf);
 		if (ret)
 			goto out;
 		io->res = result;
 		req = ublk_fill_io_cmd(io, cmd);
-		ret = ublk_config_io_buf(ub, io, cmd, addr, &buf_idx);
+		ublk_apply_io_buf(ub, io, cmd, addr, &auto_buf, &buf_idx);
 		if (buf_idx != UBLK_INVALID_BUF_IDX)
 			io_buffer_unregister_bvec(cmd, buf_idx, issue_flags);
 		compl = ublk_need_complete_req(ub, io);
@@ -3456,10 +3461,8 @@ static int ublk_ch_uring_cmd_local(struct io_uring_cmd *cmd,
 			req->__sector = addr;
 		if (compl)
 			__ublk_complete_rq(req, io, ublk_dev_need_map_io(ub), NULL);
-
-		if (ret)
-			goto out;
 		break;
+	}
 	case UBLK_IO_NEED_GET_DATA:
 		/*
 		 * ublk_get_data() may fail and fallback to requeue, so keep
@@ -3467,8 +3470,7 @@ static int ublk_ch_uring_cmd_local(struct io_uring_cmd *cmd,
 		 * request
 		 */
 		req = ublk_fill_io_cmd(io, cmd);
-		ret = ublk_config_io_buf(ub, io, cmd, addr, NULL);
-		WARN_ON_ONCE(ret);
+		io->buf.addr = addr;
 		if (likely(ublk_get_data(ubq, io, req))) {
 			__ublk_prep_compl_io_cmd(io, req);
 			return UBLK_IO_RES_OK;
-- 
2.25.1


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

* [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit
  2026-07-30  1:09 [PATCH v2 0/2] ublk: fix auto buf reg ordering around uring_cmd Yang Xiuwei
  2026-07-30  1:09 ` [PATCH v2 1/2] ublk: validate auto buf reg before taking uring_cmd Yang Xiuwei
@ 2026-07-30  1:09 ` Yang Xiuwei
  2026-07-30  2:40   ` [PATCH] selftests: ublk: add rotating auto_buf index regression test Yang Xiuwei
  2026-07-31 16:13   ` [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit Ming Lei
  1 sibling, 2 replies; 7+ messages in thread
From: Yang Xiuwei @ 2026-07-30  1:09 UTC (permalink / raw)
  To: Ming Lei, Jens Axboe; +Cc: linux-block, Caleb Sander Mateos, Yang Xiuwei

ublk_batch_commit_io() stored the new auto_buf into io->buf before
calling ublk_clear_auto_buf_reg(). Clear takes the unregister index
from io->buf.auto_reg, so it could drop the new slot and leave the
old registered buffer behind.

Fixes: 1e500e106d5a ("ublk: handle UBLK_U_IO_COMMIT_IO_CMDS")
Signed-off-by: Yang Xiuwei <yangxiuwei@kylinos.cn>
---
 drivers/block/ublk_drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index 041bd3ea023f..e12bc4ee74d3 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -3782,11 +3782,11 @@ static int ublk_batch_commit_io(struct ublk_queue *ubq,
 	ret = ublk_batch_commit_io_check(ubq, io, &buf);
 	if (!ret) {
 		io->res = elem->result;
-		io->buf = buf;
 		req = ublk_fill_io_cmd(io, data->cmd);
 
 		if (auto_reg)
 			ublk_clear_auto_buf_reg(io, data->cmd, &buf_idx);
+		io->buf = buf;
 		compl = ublk_need_complete_req(data->ub, io);
 	}
 	ublk_io_unlock(io);
-- 
2.25.1


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

* [PATCH] selftests: ublk: add rotating auto_buf index regression test
  2026-07-30  1:09 ` [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit Yang Xiuwei
@ 2026-07-30  2:40   ` Yang Xiuwei
  2026-07-31 16:24     ` Ming Lei
  2026-07-31 16:13   ` [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit Ming Lei
  1 sibling, 1 reply; 7+ messages in thread
From: Yang Xiuwei @ 2026-07-30  2:40 UTC (permalink / raw)
  To: Ming Lei, Jens Axboe, Shuah Khan
  Cc: linux-block, linux-kselftest, Caleb Sander Mateos, Yang Xiuwei

Batch AUTO_BUF_REG COMMIT must unregister the old auto_buf index before
storing the next one. Fixed per-tag indexing (A == B) masks bugs that
clear after overwriting io->buf.

Add kublk --rotate_auto_buf so each tag alternates between two sparse
buffer indices, and test_batch_04.sh to exercise that path. Without the
driver fix, the request ref stays stuck and I/O hangs; the test uses a
short timeout and kills the ublk daemon to recover. With the fix, a
small write completes quickly.

Signed-off-by: Yang Xiuwei <yangxiuwei@kylinos.cn>
---
 tools/testing/selftests/ublk/Makefile         |  1 +
 tools/testing/selftests/ublk/batch.c          |  2 +-
 tools/testing/selftests/ublk/kublk.c          | 19 +++++++-
 tools/testing/selftests/ublk/kublk.h          | 19 +++++++-
 tools/testing/selftests/ublk/test_batch_04.sh | 44 +++++++++++++++++++
 5 files changed, 82 insertions(+), 3 deletions(-)
 create mode 100755 tools/testing/selftests/ublk/test_batch_04.sh

diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile
index 6e4fe8d1fed1..b5d757aa7ee8 100644
--- a/tools/testing/selftests/ublk/Makefile
+++ b/tools/testing/selftests/ublk/Makefile
@@ -23,6 +23,7 @@ TEST_PROGS += test_generic_17.sh
 TEST_PROGS += test_batch_01.sh
 TEST_PROGS += test_batch_02.sh
 TEST_PROGS += test_batch_03.sh
+TEST_PROGS += test_batch_04.sh
 
 TEST_PROGS += test_null_01.sh
 TEST_PROGS += test_null_02.sh
diff --git a/tools/testing/selftests/ublk/batch.c b/tools/testing/selftests/ublk/batch.c
index a54025b00917..d8d9ebed5979 100644
--- a/tools/testing/selftests/ublk/batch.c
+++ b/tools/testing/selftests/ublk/batch.c
@@ -535,7 +535,7 @@ void ublk_batch_complete_io(struct ublk_thread *t, struct ublk_queue *q,
 
 	elem = (struct ublk_batch_elem *)(cb->elem + cb->done * t->commit_buf_elem_size);
 	elem->tag = tag;
-	elem->buf_index = ublk_batch_io_buf_idx(t, q, tag);
+	elem->buf_index = ublk_batch_io_buf_idx_next(t, q, tag);
 	elem->result = res;
 
 	if (!ublk_queue_no_buf(q))
diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index 0b23c09daea5..10320d9f73d1 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -540,9 +540,14 @@ static int ublk_thread_init(struct ublk_thread *t, unsigned long long extra_flag
 		unsigned max_nr_ios_per_thread = nr_ios / dev->nthreads;
 		max_nr_ios_per_thread += !!(nr_ios % dev->nthreads);
 
+		t->auto_buf_stride = max_nr_ios_per_thread;
 		t->nr_bufs = max_nr_ios_per_thread;
+		if ((extra_flags & UBLKS_Q_ROTATE_AUTO_BUF) &&
+		    (dev->dev_info.flags & UBLK_F_AUTO_BUF_REG))
+			t->nr_bufs *= 2;
 	} else {
 		t->nr_bufs = 0;
+		t->auto_buf_stride = 0;
 	}
 
 	if (ublk_dev_batch_io(dev))
@@ -1436,6 +1441,8 @@ static int ublk_start_daemon(const struct dev_ctx *ctx, struct ublk_dev *dev)
 		extra_flags = UBLKS_Q_AUTO_BUF_REG_FALLBACK;
 	if (ctx->no_ublk_fixed_fd)
 		extra_flags |= UBLKS_Q_NO_UBLK_FIXED_FD;
+	if (ctx->rotate_auto_buf)
+		extra_flags |= UBLKS_Q_ROTATE_AUTO_BUF;
 
 	for (i = 0; i < dinfo->nr_hw_queues; i++) {
 		dev->q[i].dev = dev;
@@ -2067,7 +2074,7 @@ static void __cmd_create_help(char *exe, bool recovery)
 	printf("\t[--nthreads threads] [--per_io_tasks]\n");
 	printf("\t[--integrity_capable] [--integrity_reftag] [--metadata_size SIZE] "
 		 "[--pi_offset OFFSET] [--csum_type ip|t10dif|nvme] [--tag_size SIZE]\n");
-	printf("\t[--batch|-b] [--no_auto_part_scan]\n");
+	printf("\t[--batch|-b] [--rotate_auto_buf] [--no_auto_part_scan]\n");
 	printf("\t[target options] [backfile1] [backfile2] ...\n");
 	printf("\tdefault: nr_queues=2(max 32), depth=128(max 1024), dev_id=-1(auto allocation)\n");
 	printf("\tdefault: nthreads=nr_queues");
@@ -2141,6 +2148,7 @@ int main(int argc, char *argv[])
 		{ "tag_size",		1,	NULL,  0 },
 		{ "safe",		0,	NULL,  0 },
 		{ "batch",              0,      NULL, 'b'},
+		{ "rotate_auto_buf",	0,	NULL,  0 },
 		{ "no_auto_part_scan",	0,	NULL,  0 },
 		{ "shmem_zc",		0,	NULL,  0  },
 		{ "htlb",		1,	NULL,  0  },
@@ -2228,6 +2236,8 @@ int main(int argc, char *argv[])
 				ctx.flags |= UBLK_F_AUTO_BUF_REG;
 			if (!strcmp(longopts[option_idx].name, "auto_zc_fallback"))
 				ctx.auto_zc_fallback = 1;
+			if (!strcmp(longopts[option_idx].name, "rotate_auto_buf"))
+				ctx.rotate_auto_buf = 1;
 			if (!strcmp(longopts[option_idx].name, "nthreads"))
 				ctx.nthreads = strtol(optarg, NULL, 10);
 			if (!strcmp(longopts[option_idx].name, "per_io_tasks"))
@@ -2335,6 +2345,13 @@ int main(int argc, char *argv[])
 		return -EINVAL;
 	}
 
+	if (ctx.rotate_auto_buf &&
+	    !((ctx.flags & UBLK_F_AUTO_BUF_REG) &&
+	      (ctx.flags & UBLK_F_BATCH_IO))) {
+		ublk_err("rotate_auto_buf requires --auto_zc and --batch\n");
+		return -EINVAL;
+	}
+
 	i = optind;
 	while (i < argc && ctx.nr_files < MAX_BACK_FILES) {
 		ctx.files[ctx.nr_files++] = argv[i++];
diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h
index 742c41d77df1..188b97f0cb95 100644
--- a/tools/testing/selftests/ublk/kublk.h
+++ b/tools/testing/selftests/ublk/kublk.h
@@ -82,6 +82,7 @@ struct dev_ctx {
 	unsigned int	safe_stop:1;
 	unsigned int	no_auto_part_scan:1;
 	unsigned int	rdonly_shmem_buf:1;
+	unsigned int	rotate_auto_buf:1;
 	__u32 integrity_flags;
 	__u8 metadata_size;
 	__u8 pi_offset;
@@ -134,6 +135,7 @@ struct ublk_io {
 
 	unsigned short buf_index;
 	unsigned short tgt_ios;
+	unsigned char auto_buf_phase;
 	void *private_data;
 };
 
@@ -184,6 +186,7 @@ struct ublk_queue {
 #define UBLKS_Q_AUTO_BUF_REG_FALLBACK	(1ULL << 63)
 #define UBLKS_Q_NO_UBLK_FIXED_FD	(1ULL << 62)
 #define UBLKS_Q_PREPARED	(1ULL << 61)
+#define UBLKS_Q_ROTATE_AUTO_BUF	(1ULL << 60)
 	__u64 flags;
 	int ublk_fd;	/* cached ublk char device fd */
 	__u8 metadata_size;
@@ -232,6 +235,7 @@ struct ublk_thread {
 	unsigned int io_inflight;
 
 	unsigned short nr_bufs;
+	unsigned short auto_buf_stride;
 
        /* followings are for BATCH_IO */
 	unsigned short commit_buf_start;
@@ -550,7 +554,20 @@ static inline unsigned short ublk_batch_io_buf_idx(
 		const struct ublk_thread *t, const struct ublk_queue *q,
 		unsigned tag)
 {
-	return ublk_queue_idx_in_thread(t, q) * q->q_depth + tag;
+	unsigned short base = ublk_queue_idx_in_thread(t, q) * q->q_depth + tag;
+
+	if (q->flags & UBLKS_Q_ROTATE_AUTO_BUF)
+		return base + q->ios[tag].auto_buf_phase * t->auto_buf_stride;
+	return base;
+}
+
+static inline unsigned short ublk_batch_io_buf_idx_next(
+		const struct ublk_thread *t, struct ublk_queue *q,
+		unsigned tag)
+{
+	if (q->flags & UBLKS_Q_ROTATE_AUTO_BUF)
+		q->ios[tag].auto_buf_phase ^= 1;
+	return ublk_batch_io_buf_idx(t, q, tag);
 }
 
 /* Queue UBLK_U_IO_PREP_IO_CMDS for a specific queue with batch elements */
diff --git a/tools/testing/selftests/ublk/test_batch_04.sh b/tools/testing/selftests/ublk/test_batch_04.sh
new file mode 100755
index 000000000000..cd5e1ff9d630
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_batch_04.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# --rotate_auto_buf: COMMIT must unregister old auto_buf index before store.
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+ERR_CODE=0
+
+if ! _have_feature "BATCH_IO" || ! _have_feature "AUTO_BUF_REG"; then
+	exit "$UBLK_SKIP_CODE"
+fi
+if ! _have_program fio || ! _have_program timeout; then
+	exit "$UBLK_SKIP_CODE"
+fi
+
+_prep_test "generic" "batch auto_buf unregister with rotating index"
+
+_create_backfile 0 64M
+
+dev_id=$(_add_ublk_dev_no_settle -t loop -q 1 --nthreads 1 -b --auto_zc \
+	--rotate_auto_buf "${UBLK_BACKFILES[0]}")
+_check_add_dev $TID $?
+
+for ((i = 0; i < 50; i++)); do
+	[ -b /dev/ublkb"${dev_id}" ] && break
+	sleep 0.1
+done
+[ -b /dev/ublkb"${dev_id}" ] || { _cleanup_test; _show_result $TID 1; }
+
+timeout -k 2 5 fio --name=job1 --filename=/dev/ublkb"${dev_id}" \
+	--ioengine=libaio --rw=write --direct=1 --bs=4k --iodepth=1 --size=64k \
+	> /dev/null 2>&1
+ERR_CODE=$?
+
+if [ "$ERR_CODE" -ne 0 ]; then
+	kill -9 "$(_get_ublk_daemon_pid "$dev_id" 2>/dev/null)" 2>/dev/null || true
+	sleep 0.5
+	pkill -9 fio 2>/dev/null || true
+	ERR_CODE=1
+fi
+
+_cleanup_test
+_show_result $TID $ERR_CODE
-- 
2.25.1


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

* Re: [PATCH v2 1/2] ublk: validate auto buf reg before taking uring_cmd
  2026-07-30  1:09 ` [PATCH v2 1/2] ublk: validate auto buf reg before taking uring_cmd Yang Xiuwei
@ 2026-07-31 16:10   ` Ming Lei
  0 siblings, 0 replies; 7+ messages in thread
From: Ming Lei @ 2026-07-31 16:10 UTC (permalink / raw)
  To: Yang Xiuwei; +Cc: Jens Axboe, linux-block, Caleb Sander Mateos

On Thu, Jul 30, 2026 at 09:09:09AM +0800, Yang Xiuwei wrote:
> With UBLK_F_AUTO_BUF_REG, invalid sqe->addr can fail after
> ublk_fill_io_cmd() has set UBLK_IO_FLAG_ACTIVE. The uring_cmd is
> completed while the tag stays active, which can hang teardown.
> 
> Split validation from buffer apply so the check has no side effects,
> then take the uring_cmd and store the already-validated buffer. Apply
> the same order in FETCH so io->buf is not written before __ublk_fetch()
> state checks.
> 
> Fixes: 52460dda3a77 ("ublk: move auto buffer register handling into one dedicated helper")
> Suggested-by: Caleb Sander Mateos <csander@purestorage.com>
> Signed-off-by: Yang Xiuwei <yangxiuwei@kylinos.cn>

Nice catch!

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


Thanks,
Ming

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

* Re: [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit
  2026-07-30  1:09 ` [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit Yang Xiuwei
  2026-07-30  2:40   ` [PATCH] selftests: ublk: add rotating auto_buf index regression test Yang Xiuwei
@ 2026-07-31 16:13   ` Ming Lei
  1 sibling, 0 replies; 7+ messages in thread
From: Ming Lei @ 2026-07-31 16:13 UTC (permalink / raw)
  To: Yang Xiuwei; +Cc: Jens Axboe, linux-block, Caleb Sander Mateos

On Thu, Jul 30, 2026 at 09:09:10AM +0800, Yang Xiuwei wrote:
> ublk_batch_commit_io() stored the new auto_buf into io->buf before
> calling ublk_clear_auto_buf_reg(). Clear takes the unregister index
> from io->buf.auto_reg, so it could drop the new slot and leave the
> old registered buffer behind.
> 
> Fixes: 1e500e106d5a ("ublk: handle UBLK_U_IO_COMMIT_IO_CMDS")
> Signed-off-by: Yang Xiuwei <yangxiuwei@kylinos.cn>

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

Thanks,
Ming

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

* Re: [PATCH] selftests: ublk: add rotating auto_buf index regression test
  2026-07-30  2:40   ` [PATCH] selftests: ublk: add rotating auto_buf index regression test Yang Xiuwei
@ 2026-07-31 16:24     ` Ming Lei
  0 siblings, 0 replies; 7+ messages in thread
From: Ming Lei @ 2026-07-31 16:24 UTC (permalink / raw)
  To: Yang Xiuwei
  Cc: Jens Axboe, Shuah Khan, linux-block, linux-kselftest,
	Caleb Sander Mateos

On Thu, Jul 30, 2026 at 10:40:50AM +0800, Yang Xiuwei wrote:
> Batch AUTO_BUF_REG COMMIT must unregister the old auto_buf index before
> storing the next one. Fixed per-tag indexing (A == B) masks bugs that
> clear after overwriting io->buf.
> 
> Add kublk --rotate_auto_buf so each tag alternates between two sparse
> buffer indices, and test_batch_04.sh to exercise that path. Without the
> driver fix, the request ref stays stuck and I/O hangs; the test uses a
> short timeout and kills the ublk daemon to recover. With the fix, a
> small write completes quickly.
> 
> Signed-off-by: Yang Xiuwei <yangxiuwei@kylinos.cn>

Looks fine, 

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

BTW, this selftest patch should have been part of
"[PATCH v2 0/2] ublk: fix auto buf reg ordering around uring_cmd"


Thanks,
Ming

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

end of thread, other threads:[~2026-07-31 16:25 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-30  1:09 [PATCH v2 0/2] ublk: fix auto buf reg ordering around uring_cmd Yang Xiuwei
2026-07-30  1:09 ` [PATCH v2 1/2] ublk: validate auto buf reg before taking uring_cmd Yang Xiuwei
2026-07-31 16:10   ` Ming Lei
2026-07-30  1:09 ` [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit Yang Xiuwei
2026-07-30  2:40   ` [PATCH] selftests: ublk: add rotating auto_buf index regression test Yang Xiuwei
2026-07-31 16:24     ` Ming Lei
2026-07-31 16:13   ` [PATCH v2 2/2] ublk: clear auto buf reg before updating io->buf in batch commit Ming Lei

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