* [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
* 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
* [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] 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
* 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
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