* [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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.