Skip to content

Niova ublk 7.1 fix backports - #3

Open
bsbernd wants to merge 91 commits into
niova-ublk-7.1from
niova-ublk-7.1-fix-backports
Open

Niova ublk 7.1 fix backports#3
bsbernd wants to merge 91 commits into
niova-ublk-7.1from
niova-ublk-7.1-fix-backports

Conversation

@bsbernd

@bsbernd bsbernd commented Sep 8, 2026

Copy link
Copy Markdown

No description provided.

bsbernd and others added 30 commits August 14, 2026 13:26
Move ublk_req_build_flags() above its callers so it doesn't need to be
forward-declared.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260520203654.1413640-2-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit eee9224)
The code for initializing struct ublksrv_io_desc on I/O dispatch is
largely duplicated in 3 places. Commit 4d4a512 ("ublk: add PFN-
based buffer matching in I/O path") added support to ublk_setup_iod()
for matching request buffers against registered UBLK_F_SHMEM_ZC buffers,
but missed adding it to ublk_setup_iod_zoned() for zoned requests. Move
the duplicated logic to a new helper ublk_init_iod(). This way, zone
appends can also benefit from avoiding the data copy.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260520203654.1413640-3-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 23130b3)

The cherry pick to 7.1-niova differs in respect to blk_rq_has_data():
that inline came with 999722b ("blk-mq: introduce
blk_rq_has_data()"), which 7.1 does not have. ublk_rq_has_data() stays
and moves above ublk_init_iod(), so the call site still sees a
declaration.
ublk_start_cancel() previously bailed out early when ublk_get_disk()
returned NULL, treating it as "our disk has been dead".  That is correct
for the post-teardown case, but it also wrongly covers the pre-start
case: ublk_ctrl_start_dev() has not assigned ub->ub_disk yet, while
io_uring is already tearing down the daemon's uring_cmds via
ublk_uring_cmd_cancel_fn().

In that window, the cancel path skips ublk_set_canceling(), so
ubq->canceling stays false, even though ublk_cancel_cmd() goes on to
NULL out every io->cmd.  ublk_ctrl_start_dev() then proceeds to set
ub->ub_disk, call add_disk(), and schedule partition_scan_work.  When
ublk_partition_scan_work() runs bdev_disk_changed() and the resulting
read reaches ublk_queue_rq() -> ublk_queue_cmd(), the ubq->canceling
check passes and the code dereferences the NULL io->cmd:

  BUG: kernel NULL pointer dereference, address: 0000000000000018
  RIP: ublk_queue_cmd drivers/block/ublk_drv.c [inline]
  RIP: ublk_queue_rq+0x73/0x100
  Call Trace:
   blk_mq_dispatch_rq_list+0x1c5/0xca0
   ...
   bdev_disk_changed+0x3d4/0x5e0
   ublk_partition_scan_work+0x89/0xe0
   process_one_work+0x344/0x8a0

Fix it by always setting ub->canceling / ubq->canceling under
cancel_mutex.  When the disk is allocated, keep the existing
quiesce/unquiesce dance so the flag is observed across the
ublk_queue_rq() barrier.  When the disk is not yet allocated, there is
no request_queue and ublk_queue_rq() cannot be running concurrently, so
simply flipping the flag is sufficient: any subsequent I/O - including
the partition scan started by ublk_ctrl_start_dev() - will see
canceling set and be aborted via __ublk_queue_rq_common().

Fixes: 7fc4da6 ("ublk: scan partition in async way")
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260527144042.2095194-1-tom.leiming@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 1133b93)
The batch prepare path rereads its userspace element array when rolling
back a partially prepared batch. Userspace can change an already
processed tag before the second read, causing rollback to reject the
replacement tag and leave earlier I/O slots prepared. The
WARN_ON_ONCE() in the rollback path then fires.

Copy the bounded batch into kernel memory before changing any I/O state
and use the same snapshot for preparation and rollback. Commit and fetch
batches retain the existing chunked userspace walk.

Fixes: b256795 ("ublk: handle UBLK_U_IO_PREP_IO_CMDS")
Reported-by: syzbot+1a67ee1aa79484801ec6@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=1a67ee1aa79484801ec6
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260630211827.50475-1-alhouseenyousef@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit f01f5275feb77bac9fefbbf7cc584fe0b3850a92)
ub->completion is only re-armed by a successful START_USER_RECOVERY. If
the ublk server sends END_USER_RECOVERY without one - e.g. its START
failed with -EBUSY and the error was ignored - the wait is satisfied by
the stale completion of the previous recovery cycle, and the device is
marked LIVE and the requeue list kicked while the FETCH stream is still
running and ubq->canceling is still set. The kick redispatches a
previously requeued request, __ublk_queue_rq_common() sees ->canceling
and parks it again via __ublk_abort_rq(), and after the last FETCH
clears ->canceling nothing ever kicks the requeue list again: the
request is stranded there while holding its tag. If it is the flush
machinery's flush_rq, every subsequent fsync piles up in uninterruptible
sleep and teardown hangs on tag draining. This matches a report of a
lost PREFLUSH with ext4 on top of ublk after daemon crash recovery.

ub->completion is an edge-triggered latch used as a proxy for the level
condition "every queue has fetched all I/O commands", which can regress
(F_BATCH's UNPREP, daemon death) and whose re-arm can be skipped. Drop
it and wait on the real condition instead: the new helper
ublk_wait_dev_ready_and_lock() waits on ublk_dev_ready() via
wait_var_event_interruptible(), woken from ublk_mark_io_ready(), then
re-checks it under ub->mutex, waiting again on regression, and returns
with the mutex held and readiness guaranteed.

Readiness becomes true in the same ub->mutex critical section that
clears the last queue's ->canceling, so END_USER_RECOVERY marks the
device LIVE and kicks the requeue list strictly after ->canceling
clears. The wait stays interruptible, so a server whose daemon died can
still be signalled out. For ublk_ctrl_start_dev() this replaces the
fail-fast -EINVAL on an F_BATCH ready->UNPREP regression with waiting
until the device is ready again.

Reported-by: George Salisbury <gsalisbury@apnic.net>
Fixes: 728cbac ("ublk: move device reset into ublk_ch_release()")
Cc: stable@vger.kernel.org
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260719134540.120269-1-tom.leiming@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 432a9b2780c0a01caf547bd1fc2fcf28aeb8d173)
ublk_ctrl_add_dev() memcpy()s the userspace ublksrv_ctrl_dev_info into
ub->dev_info and then fixes up the fields the driver owns, but misses
->state and ->ublksrv_pid.

A device added with ->state = UBLK_S_DEV_LIVE passes the
"->state != UBLK_S_DEV_DEAD" test that ublk_stop_dev_unlocked() uses as its
proxy for "a disk is attached", while ->ub_disk is still NULL, so DEL_DEV
right after ADD_DEV oopses in del_gendisk().  UBLK_S_DEV_QUIESCED plus
UBLK_F_USER_RECOVERY dies one step earlier, in ublk_force_abort_dev().  A
poisoned ->state also gets START_USER_RECOVERY and the char device
read/write path onto a device that was never started, and wedges START_DEV
at -EEXIST.  A poisoned ->ublksrv_pid just makes GET_DEV_INFO report an
unrelated task as the ublk server.

Reset both after the memcpy(), as ublk_detach_disk() does.  Userspace only
ever reads these back, so correcting them silently breaks nothing.

ADD_DEV has copied ->state in unsanitized since ublk was merged, but back
then it was harmless: the gendisk was allocated during ADD_DEV, and both
teardown and the START_DEV -EEXIST check keyed off disk_live() rather than
->state.  The oops became reachable once the disk allocation moved to
START_DEV and those checks switched to ->state.

Fixes: 6d9e6df ("ublk: defer disk allocation")
Cc: stable@vger.kernel.org
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
Link: https://patch.msgid.link/20260726145025.1507383-1-tom.leiming@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit e65848e4ce352bac9e3465099354c8b8f845391f)
import_ubuf() can fail if the address range (provided by the userspace
ublk server) is outside the allowed user address space. Return that 0
bytes were copied if import_ubuf() fails rather than passing an
uninitialized struct iov_iter to ublk_copy_user_pages().

Fixes: 981f95a ("ublk: cleanup ublk_copy_user_pages")
Reported-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Link: https://patch.msgid.link/20260729171041.45061-2-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 3831568792af75b6523fa93bb91560e29189cf55)
If the userspace ublk server passes an unmapped address as the data
buffer for a completed ublk read, ublk_unmap_io() will return 0
indicating no bytes could be copied. Currently, this will result in
calling blk_update_request() with nr_bytes=0, which doesn't seem
supported. Fail the I/O with BLK_STS_IOERR in this case instead.

Fixes: 71f28f3 ("ublk_drv: add io_uring based userspace block driver")
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Link: https://patch.msgid.link/20260729171041.45061-3-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 24fd3706178f1ae5501fd1ff9036e170ed0665ba)
io->res is set from struct ublksrv_io_cmd's result field, which is
controlled by the ublk server process, without any validation. It's thus
possible for userspace to trigger the io->res > rq_bytes warning.
ublk_copy_user_pages() already limits the copy length to the request
data length, so drop the warning.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Link: https://patch.msgid.link/20260729171041.45061-4-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 15c1339ef44054cc79c49b40b24a26aa80a2253e)
The u16 nr_hw_queues and queue_depth fields of the ublk UAPI struct
ublksrv_ctrl_dev_info constrain the number of queues and queue depth of
each ublk device. However, the ublk driver is a bit inconsistent with
the type it uses to represent these values, mixing u16 with int and
unsigned int. Change all queue number, queue depth, q_id, and tag
variables/fields to u16 to save some space.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260803211441.2538144-2-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit f510198855b6ddac0ffe62684dc407c56d3e0f24)
struct ublk_zoned_report_desc's operation field is only ever set to
UBLK_IO_OP_REPORT_ZONES, so remove it. Replace its one load with the
constant.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260803211441.2538144-3-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 3a00b782a7b63b1876261ab883e1d8e1aa0e09fb)
In preparation for moving the struct ublksrv_io_desc initialization from
the thread submitting ublk requests to the daemon thread receiving them,
split the fallible part of ublk_setup_iod{,_zoned}() into new helper
ublk_validate_req{,_zoned}(). Only ublk_setup_iod{,_zoned}() accesses
the io_desc and cannot error out.

Return a bool value from ublk_validate_req{,_zoned}() as the existing
error code ublk_setup_iod{,_zoned}() returns is only checked against
BLK_STS_OK.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260803211441.2538144-4-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 8c76625ff9360cbe9ce0c47a624877aea14b3499)
ublk_setup_iod() is currently called to populate struct ublksrv_io_desc
on the thread submitting I/O to a ublk device. However, only the ublk
server threads read the io_descs. This basically guarantees a cache miss
on both threads for each ublk I/O. There's really no need to initialize
the io_descs on the submitting thread. Move the ublk_setup_iod() call to
ublk_dispatch_req() (for non-UBLK_F_BATCH_IO) and
__ublk_batch_prep_dispatch() (for UBLK_F_BATCH_IO), which runs on the
ublk server daemon thread before dispatching the I/O to userspace.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260803211441.2538144-5-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 735409f58b3da45094f2dfd7c18fb9e1937431f1)
ublk passes the parameters of incoming I/O in memory shared between the
kernel ublk driver and userspace ublk server in struct ublksrv_io_desc.
The size of this struct is currently fixed to 24 bytes, which has been
an obstacle to extending it with additional fields [1]. Additionally,
with multiple ublk server threads handling I/Os from the same ublk queue
(possible with UBLK_F_PER_IO_DAEMON or UBLK_F_BATCH_IO), false sharing
results from adjacent io_descs sharing the same cache line.

Add a ublk feature UBLK_F_IO_DESC_SIZE to allow a ublk server to
override the size of each io_desc. The size must be at least 24 and a
multiple of 8 to store a properly-aligned struct ublksrv_io_desc. It's
also limited to a maximum of 256, though this bound could be lifted in
the future.

The struct ublksrv_io_desc is located at the beginning of each io_desc
and the remainder is padding. The mmap() performed for each queue must
have a length of queue_depth * io_desc_size rounded up to the page size.
The mmap() offset must be q_id * UBLK_MAX_QUEUE_DEPTH * io_desc_size,
also rounded up to the page size.

[1]: https://lore.kernel.org/linux-block/aV8QfvaNO5P6vOs6@fedora/

Suggested-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Link: https://patch.msgid.link/20260803211441.2538144-6-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 5c0958d80190822c4614ca00478d9acd9671bba6)
Add an optional --io_desc_size argument to the kublk add/recover
commands to enable UBLK_F_IO_DESC on the ublk device. The mmap()
arguments and ublk_get_iod() computation are adjusted accordingly.

Display the configured io_desc_size in the kublk list output for ublk
devices with UBLK_F_IO_DESC.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Link: https://patch.msgid.link/20260803211441.2538144-7-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit fc01b96d74b3a9eec2b558d49ec9f5176473766a)
Add test loop_08, which creates a ublk device with UBLK_F_IO_DESC_SIZE
enabled and io_desc_size set to 64. The test issues verified I/O to the
device using fio.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Link: https://patch.msgid.link/20260803211441.2538144-8-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit d61d0f95e686be015cfaf193c0ae15156d1a0cc4)
ublk_map_io() and ublk_unmap_io() are no-ops for ublk devices that
enable user copy or zero copy, as well as for requests without data to
copy in the given direction. However, the implementation is a bit
convoluted, returning the full request data length and relying on the
caller to check the return value against the request length.
UBLK_F_SHMEM_ZC recently added branches to skip the ublk_{,un}map_io()
call for I/Os using a shared-memory buffer. This is a more logical place
for the device need_map and the ublk_need_{,un}map_req() checks, so move
them there from ublk_{,un}map_io().

Checking these conditions early also skips the expensive pointer-chasing
for the ublk_iod_is_shmem_zc() check in __ublk_complete_rq() for the
common case of a ublk device using user copy or zero copy.

Drop the req_op() filter in __ublk_complete_rq(), as it's redundant with
the ublk_need_unmap_req() check.

Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260803211441.2538144-9-csander@purestorage.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit a8a79eba22dc4c11f2877bcf9e8557f6d95541ac)
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: 52460dd ("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>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit ca5a01eee34c7cbe0f531a613b0292a3ad1a419b)
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>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260730024050.1062354-1-yangxiuwei@kylinos.cn
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit d507d3cb19e71f10336e41deeac517cdc21c34ea)
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: 1e500e1 ("ublk: handle UBLK_U_IO_COMMIT_IO_CMDS")
Signed-off-by: Yang Xiuwei <yangxiuwei@kylinos.cn>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit af0955c8f26aa0f02e534084bc9948a69c9e7ce0)
UBLK_F_ZONED uses params.basic.chunk_sectors as zone size. ublk uses
ilog2(chunk_sectors) to get number of zones, so the value must be power
of 2.

If chunk_sectors is 96 and dev_sectors is 96 * 16, userspace asks for
16 zones. But the shift calculation gets 24 zones.

Block layer rejects such zone size when the disk is started. But
SET_PARAMS has already returned success, which is confusing for
userspace. Reject it in SET_PARAMS with other zoned parameter checks.

Fixes: 29802d7 ("ublk: enable zoned storage support")
Signed-off-by: Yao Sang <sangyao@kylinos.cn>
Link: https://patch.msgid.link/20260814023226.354288-2-sangyao@kylinos.cn
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 2707acf1856da266139986c9398ad722fd4f48c0)
The normal kublk add command goes through device startup. It does not
tell the shell test whether a bad parameter is rejected by SET_PARAMS or
later by START_DEV.

Add a set_params command. It creates a temporary ublk device, sends
SET_PARAMS with the command line parameters, returns the ioctl result,
and deletes the device before START_DEV.

Signed-off-by: Yao Sang <sangyao@kylinos.cn>
Link: https://patch.msgid.link/20260814023226.354288-3-sangyao@kylinos.cn
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 176f02a86c0384df4ba175e319321b07089a8016)
Add test_params_01.sh for SET_PARAMS. The test checks valid basic
parameters and several invalid parameter cases.

Also cover zoned parameters, including a non-power-of-2 zone size. This
case must fail in SET_PARAMS instead of being accepted and rejected later
when the device is started.

Signed-off-by: Yao Sang <sangyao@kylinos.cn>
Link: https://patch.msgid.link/20260814023226.354288-4-sangyao@kylinos.cn
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 007af5e5cc822aed3a0909534ffb810f7816ed1f)
__ublk_shmem_remove_ranges() removes matching maple tree ranges in
batches, but first stores each range into a temporary xarray so that the
pages can be unpinned after dropping the maple tree lock.

That temporary xarray is filled under the maple tree lock with
xa_store(..., GFP_ATOMIC). If the store fails before mas_erase(), the
current range is left in the tree and the helper returns false. The
outer ublk_shmem_remove_ranges() loop then immediately retries the same
range. While the atomic allocation keeps failing, the teardown path has
no forward progress.

The issue can be reproduced with radix_tree_node failslab injection after
a SHMEM_ZC buffer has already been registered:

  # Kernel config:
  #   CONFIG_BLK_DEV_UBLK=y
  #   CONFIG_DEBUG_FS=y
  #   CONFIG_FAULT_INJECTION=y
  #   CONFIG_FAULT_INJECTION_DEBUG_FS=y
  #   CONFIG_FAILSLAB=y

  echo 10 > /proc/sys/vm/nr_hugepages
  mkdir -p /tmp/htlb
  mount -t hugetlbfs none /tmp/htlb
  fallocate -l 4M /tmp/htlb/ublk_buf

  dev_id=$(kublk add -t null --shmem_zc \
		--htlb /tmp/htlb/ublk_buf |
	   awk -F '[ :]' '/dev id/ {print $3}')

  echo 1 > /sys/kernel/slab/radix_tree_node/failslab
  echo Y > /sys/kernel/debug/failslab/cache-filter
  echo Y > /sys/kernel/debug/failslab/ignore-gfp-wait
  echo 1 > /sys/kernel/debug/failslab/interval
  echo -1 > /sys/kernel/debug/failslab/times
  echo 100 > /sys/kernel/debug/failslab/probability

  kublk del -n "$dev_id"

On the unfixed kernel the delete command was still running after 3
seconds. Disabling failslab made it return. The fault-injection stack
showed:

  should_failslab
  kmem_cache_alloc_lru_noprof
  __xas_nomem
  __xa_store
  xa_store
  __ublk_shmem_remove_ranges
  ublk_cdev_rel
  ublk_ctrl_del_dev

Remove the allocation from the teardown loop. Keep the existing batch
limit, but collect {base_pfn, nr_pages} pairs in a fixed-size stack array.
Once a matching range is found, the range is erased from the maple tree
before dropping the lock, so each successful scan makes progress without
depending on any GFP_ATOMIC allocation.

With the same failslab settings, the fixed kernel completed
"kublk del -n $dev_id" successfully in about 45 ms.

Fixes: 309e02d ("ublk: avoid unpinning pages under maple tree spinlock")
Signed-off-by: Yao Sang <sangyao@kylinos.cn>
Reviewed-by: Ming Lei <tom.leiming@gmail.com>
Link: https://patch.msgid.link/20260804125736.2011774-1-sangyao@kylinos.cn
Signed-off-by: Jens Axboe <axboe@kernel.dk>
(cherry picked from commit 4fd66a7f829f3f38f92a79081f0f2688aed644f0)
UBLK_CMD_GET_FEATURES returns UBLK_F_ALL, which lists UBLK_F_ZONED
unconditionally. Built with CONFIG_BLK_DEV_ZONED=n the driver then
refuses the device it just advertised: ublk_ctrl_add_dev() returns
-EINVAL for a zoned request, and ublk_dev_param_zoned_validate()
returns -EOPNOTSUPP.

A ublk server has no other way to ask, so it takes the feature bit at
its word and fails at ADD_DEV. test_params_01.sh does exactly that: it
gates its zoned cases on the reported feature, so on such a kernel the
first case fails and the remaining ones pass only because creating the
device fails before any parameter is validated.

Clear the bit in the reported feature set. UBLK_F_ALL itself is left
alone: ublk_ctrl_add_dev() masks dev_info.flags with it before testing
for a zoned device, so removing the bit from the mask would drop the
request instead of refusing it, and hand back a non-zoned device.

Fixes: 29802d7 ("ublk: enable zoned storage support")
Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
The driver's own state cannot be read from userspace. The control
device reports what was configured, not what the driver is doing with
it, and a device that is being torn down is unreachable through both
/dev/ublkcN and the control device while its state is exactly what is
wanted.

Add a generic inspection point under ublk/<dev_id>/:

  dev_state  device state and flags, the per queue flags, and the
             device reference count
  tags       one line per tag in use - io->flags, the parked command,
             the request handed to the ublk server, the reference
             counts, the serving task, and whether the request is
             started

Tag state is copied under io->lock and printed outside it.

A device outlives its deletion whenever something still holds it, and
that is the state worth reading, so ublk_cdev_rel() removes the
directory at the final put rather than ublk_remove() at deletion. That
removal runs before the queues and the tag set the files report on are
freed, and debugfs_remove_recursive() waits out readers already inside
a file operation and refuses any that start later, so no reader can
reach a device that is going away.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
ublk/<dev_id>/dev_state and ublk/<dev_id>/tags are the only view of
per-tag state from userspace, and the teardown cases added later take
their verdict from them.  Cover the files themselves first: that they
report the geometry the device was created with, that tags stays
readable while ublk_debugfs_tags_show() walks state the IO path is
changing underneath, and that the directory goes away with the device.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
A device that will not go away says nothing about how far its teardown
got. The end state is all that can be read, and it does not answer
whether the character device was ever released, whether the queued task
work ran, or whether a parked command was ever offered to cancellation.

Record it. ublk/<dev_id>/teardown lists the lifecycle steps a device
reached, and counts the events that only make sense compared against
each other: task work queued against task work run, and cancellation
calls against what they did.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
bsbernd and others added 30 commits September 7, 2026 14:41
ublk_batch_cancel_queue() sets ubq->force_abort so that no further batch
fetch command attaches while the queue is being cancelled. Recovery resets
the queue through ublk_queue_reset_io_flags(), which clears ->canceling and
->fail_io but leaves ->force_abort set.

A UBLK_F_BATCH_IO device that went through UBLK_CMD_QUIESCE_DEV therefore
cannot be recovered. END_USER_RECOVERY reports success and the device goes
LIVE, but the recovered server's UBLK_U_IO_FETCH_IO_CMDS is refused by
ublk_batch_attach(), which tests ->force_abort together with ->canceling.
Its IO threads exit at once, the server dies, and a UBLK_F_USER_RECOVERY
device falls straight back to QUIESCED:

    state: QUIESCED
    ublksrv_tgid: -1
    queue 0: depth 64 canceling 1 force_abort 1 fail_io 0 nr_io_ready 0

Clear it with the rest. The classic cancel path never sets ->force_abort per
queue, which is why only batch devices are affected; the other setters are
teardown paths where the device is going away.

Fixes: a4d8837 ("ublk: add UBLK_U_IO_FETCH_IO_CMDS for batch I/O processing")
Cc: stable@kernel.org
Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
ublk_wait_for_idle_io() returns immediately for UBLK_F_BATCH_IO, so
QUIESCE_DEV runs its single cancel pass against whatever the queues hold at
that moment, and the server learns about the quiesce only if an fcmd was
cancellable there.  Every quiesce case so far creates a non-batch device, so
neither that early return nor ublk_batch_cancel_queue() behind it has been
covered.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
del_gendisk() waits for requests that were started, and teardown looked
for them by scanning io->flags for UBLK_IO_FLAG_OWNED_BY_SRV. That scan
has to enumerate every state a tag can hold, and it reads the request out
of the cmd/req union, which is only valid for the state it just tested.

Walk blk_mq_tagset_busy_iter() instead. Only started requests reach the
callback, so the set teardown ends is the set del_gendisk() waits for,
the request comes from the tag rather than the union, and a state that
holds no request needs no arm in the walk.

A tag being dispatched is owned by the dispatcher for that whole
interval and is skipped: it ends its own request once it observes
->canceling. Anything the walk finds started but unowned is a bug rather
than work to do, and stalls the freeze that follows.

The iterator covers the whole tag set, so the per-queue
ublk_abort_queue() gives way to ublk_abort_dev(), which drains the batch
event fifos and then walks once.

The scan being removed here is the one "ublk: serialize tag state and
command claims" takes io->lock across earlier in this series. Both are
needed on their own: that commit closes the fill-versus-cancel race on
every tag and applies without this one, while this commit is about which
requests del_gendisk() is left waiting for.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
Fixes: 71f28f3 ("ublk_drv: add io_uring based userspace block driver")
Cc: stable@kernel.org
io_uring_prep_timeout() records only the pointer to the timespec, and
ublk_fault_inject_queue_io() puts it on its own stack. The kernel reads
it when the event loop submits, after that frame is gone.

The stale bytes parse as an expired timeout, so --delay_us never delays
and test_generic_06.sh fails: dd completes before the daemon is killed.
A delay above 999999us could not work either, being stored in tv_nsec
alone.

Fixes: 8158665 ("selftests: ublk: add generic_06 for covering fault inject")
Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
blk_mq_tagset_busy_iter() must end exactly the set del_gendisk() waits for,
and a request the walk finds started but unowned stalls the freeze that
follows. Every existing delete case runs a null device, which completes at
once and rarely has a request with the ublk server when the delete lands.

1M writes to a backing file keep requests there, and the batch and auto_zc
arms go through the same walk, which covers the whole tag set rather than a
queue at a time.

A backing file only makes the state likely. The fault_inject target makes
it certain: it answers each IO with a timeout, so every fetched tag stays
OWNED_BY_SRV for as long as the delay lasts and the delete meets a full
queue of them.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
io_uring runs pending task work with io_tw_token_t.cancel set when the ring
goes away, so the driver can finish what it queued.  ublk_batch_tw_cb()
ignored the token and went on to dispatch.

A fetch command is ubq->active_fcmd while its task work is outstanding, and
ublk_batch_cancel_cmd() deliberately skips the active one, so a command left
parked in that run is stranded: it keeps referencing the ublk char device
and UBLK_U_CMD_DEL_DEV waits on ublk_idr_wq forever.

Give back the queued tags and unwind the fetch command through
ublk_batch_deinit_fetch_buf(), which is already the "nothing can move on"
path.  Report UBLK_IO_RES_ABORT, as ublk_batch_cancel_cmd() does for the
same command: the ublk server decides whether to fetch again by comparing
against it.

Fixes: a4d8837 ("ublk: add UBLK_U_IO_FETCH_IO_CMDS for batch I/O processing")
Cc: stable@kernel.org

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
A ublk server that goes away leaves the device live with no STOP_DEV ever
sent, and io_uring then runs the task work it queued with cancel set. For
UBLK_F_BATCH_IO that run is the only chance the fetch command gets: it is
ubq->active_fcmd, which ublk_batch_cancel_cmd() skips, so a command left
parked there keeps referencing /dev/ublkcN and UBLK_U_CMD_DEL_DEV waits on
ublk_idr_wq for ever.

kublk had no shutdown of its own, so nothing could reach that ordering.
The teardown modes added here run on a sigwait() thread, because
ublk_ctrl_stop_dev() submits on the control ring and is not
async-signal-safe; later cases take the same route.

Whether task work is outstanding at the instant the ring dies is not
something the test can arrange, so it kills at a different point each cycle
and takes many cycles rather than one. --die_during_fetch is not an
alternative: the fault_inject target raises SIGKILL only for tag 1, and the
batch path calls pre_fetch_io once per queue with tag 0, so a batch server
never dies there.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
Without recovery, ublk_stop_dev() entered del_gendisk() while requests
could still be owned by the live server:

    ublk_stop_dev()
    del_gendisk()
        waits for an OWNED_BY_SRV request
    the request is only failed once the server is gone

Publish ->canceling and fail those requests before del_gendisk() starts
waiting, by calling ublk_abort_dev() there too. It now publishes
->canceling through ublk_start_cancel(), so the char device release path
gains the quiesce that ublk_set_canceling() asks its callers for.

ublk_cancel_dev() stays outside ub->mutex and ub->cancel_mutex:
->cancel_fn() takes cancel_mutex under ->uring_lock, and the submission
path takes ub->mutex under it, so completing a command from under either
mutex inverts the order. del_gendisk() waits for requests, and a parked
command holds none, so the cancel is not needed before it.

Fixes: 71f28f3 ("ublk_drv: add io_uring based userspace block driver")
Cc: stable@kernel.org
Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
del_gendisk() waits for started requests, and only the server ends a request
it owns, so teardown has to fail those itself before it gets there.  Nothing
in the suite held a request across a delete, so the ordering was never
exercised.

--hold_io stops the server completing what it fetched, leaving the tag
UBLK_IO_FLAG_OWNED_BY_SRV.  The test asserts that state through debugfs
before deleting: a delete that finds no owned request proves nothing.

Unlike the other teardown cases this needs no race - the server simply never
commits - so a single run either reproduces or does not.

Replaces selftests-cmd-path, which iterated copy modes on healthy devices and
never reached the window.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
A request that ublk_abort_dev() fails to dispose of blocks del_gendisk()
in blk_mq_freeze_queue_wait() forever, holding ublk_ctl_mutex and
ub->mutex, so every later control command wedges behind it. Nothing in
dmesg names the tag, and io->flags is not reachable from userspace once
the device is being torn down.

ublk/<dev_id>/tags carries the same state, but only for someone already
watching on a CONFIG_DEBUG_FS=y kernel; pr_warn() reaches a bug report
and a test run's log.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
ublk_queue_cmd_list() handed a chain of requests spanning several tags to
one carrier command's task work, and ublk_cmd_list_tw_cb() walked it by
rq_next.  Nothing but that callback could reach those requests, so
teardown has no way to dispose of a dispatch whose task work never runs.

Put the requests on a per-queue list instead, the way UBLK_F_BATCH_IO
already queues tags on evts_fifo, and let the task work take them off it.
A queued request then belongs to whoever unlinks it under disp_lock.

A task work only takes an entry when it may dispatch it: the tag has to
belong to the running task, so UBLK_F_PER_IO_DAEMON keeps dispatching
every tag from its own daemon, and the tag must have no task work of its
own queued, because dispatching hands its command over and only the
callback queued on a command may complete it.  Track the latter with
UBLK_IO_FLAG_CMD_TW_PENDING.

For the same reason a batch no longer spans queues, as each queue has its
own list.

The two disposal paths belong in the same commit as the list itself,
because a list nobody can drain strands the requests on it:

 - teardown takes the queued requests back in ublk_abort_dev(), as is
   already done for the batch event fifo.  A request whose dispatch task
   work never runs otherwise stays started for ever, so
   blk_mq_freeze_queue_wait() in del_gendisk() never returns, and
   ublk_stop_dev() holds ublk_ctl_mutex and ub->mutex across that wait --
   one such device wedges every other control command on the machine:

     ublk_warn_started_rq: dev 0 qid 1 tag 63 still started: io_flags 5

 - io_uring runs pending task work with io_tw_token_t.cancel set when the
   ring goes away, in io_cancel_local_task_work() from
   io_ring_exit_work(), so the driver can finish what it queued.  That run
   is the only chance the command gets: cancellation refuses a command
   with a dispatch in flight, so a command left parked there is stranded,
   keeps referencing the ublk char device, ublk_ch_release() never runs,
   and UBLK_U_CMD_DEL_DEV waits on ublk_idr_wq for ever.  Give back the
   queued requests and complete the command, the way
   fuse_uring_send_in_task() does.  Every entry is taken there rather than
   only this task's, since no dispatch follows and one left behind would
   strand its request as well.

Cancellation keeps its UBLK_IO_FLAG_DISPATCHING test, taken under
io->lock, so a tag that ublk_prep_req() has taken for dispatch is still
held against cancellation.  But teardown clears that flag on the requests
it takes back, so it no longer covers a dispatch whose task work is still
queued.  Add the started request as a second test, in the same locked
section.

UBLK_IO_FLAG_CMD_TW_PENDING must not be used for this: only
ublk_cmd_tw_cb() ever clears it, and a task work armed on a ring that is
going away is never run.  The tag then stays ACTIVE with the flag set,
ublk_cancel_cmd() refuses it for ever and io_ring_exit_work() spins on it
at 100% of a core:

    io_ring_exit_work -> io_uring_try_cancel_requests
      -> io_uring_try_cancel_uring_cmd -> ublk_ch_uring_cmd

Measured with per-tag counters: for every stranded tag the command had
been armed exactly one more time than the callback had run, and it never
caught up.  A started request instead un-starts when teardown ends it, so
that test lifts whether or not the task work is ever run.
UBLK_IO_FLAG_CMD_TW_PENDING still marks which entries a task work may
take in ublk_take_dispatch_list().

ublk_queue_cmd_list() also has to take the command under the same
ublk_io_lock() that marks the task work pending.  ublk_prep_req() checks
->canceling, but nothing holds that gate until the command is consumed:
teardown aborting any request of the batch calls ublk_undo_dispatch(),
which clears UBLK_IO_FLAG_DISPATCHING, and cancellation then clears
->cmd under the submitter, which arms task work on NULL:

    BUG: kernel NULL pointer dereference, address: 000000000000004b
    RIP: 0010:__io_uring_cmd_do_in_task+0x9/0x30
    Call Trace:
     ublk_queue_rqs+0x12e/0x1c0 [ublk_drv]
     blk_mq_dispatch_queue_requests+0xca/0x360
     blk_mq_flush_plug_list+0x177/0x1c0

Taking it under the lock leaves cancellation either before us, so the
command is already gone and the requests go to ublk_abort_dispatch_queue()
instead, or after us, where it finds the tag no longer idle.  That helper
pops under disp_lock, so a request is disposed of by whoever pops it and
teardown draining concurrently cannot dispose of it twice.

Squashed from three patches ("queue classic dispatches on a per-queue
list", "abort dispatches still queued at teardown", "complete the command
when task work runs in cancel mode").  Testing showed the first two are
not usable apart: with only the list and the teardown drain, generic/002,
generic/004, generic/005 and generic/006 of the ublksrv test suite
(https://github.com/ublk-org/ublksrv) all fail; the cancel-mode
completion is what brings 004, 005 and 006 back.  Splitting them again
would put a commit into the tree that hangs every device-delete test and
wedges the control path.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
Requests queued on ubq->disp_list are reachable only from the task work
armed on the tag's command, so when the ring goes away that one cancel-mode
run is the only chance they get. A run that dispatches instead of giving
them back leaves them started, del_gendisk() waits for them, and
ublk_stop_dev() holds ublk_ctl_mutex across that wait.

The batch case covers this from the fetch command's side; this covers the
classic path, including the per-io-task arm where a request can sit on a
list its own task work is not the one to drain.

A server started with --abandon_ring closes its rings on the signal but
keeps /dev/ublkcN open and parks in pause(), so it has to be killed from
outside, and before the delete rather than after it: DEL_DEV waits for the
last reference on the char device to go.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
UBLK_CMD_DEL_DEV waits for the device number to leave the idr, and that
only happens in ublk_cdev_rel(), on the last reference to the char
device.  A ublk server holds those references itself: every parked
command is an io_uring request pinning the ublkc file.

So a server that deletes its own device can wait forever.  It has to
exit for the references to go, and it cannot exit while the delete has
not returned:

  ublk_ctrl_del_dev+0x117 [ublk_drv]
  ublk_ctrl_uring_cmd+0x2b3 [ublk_drv]

Nothing about the device is unfinished at that point.  ublk_remove() has
stopped it, taken the requests back, removed the disk and completed
every parked command, and ublk_start_cancel() has already made it
impossible to park another one.  Free the number there instead, and let
the rest of the device go when its last reference does.

The number becomes reusable while the device is still there, so
ublk/<dev_id>/ cannot keep that name: ublk_remove() moves the device to
ublk/stale/<n>, and ublk_cdev_rel() removes it at the final put. A
directory under stale/ is therefore a device that was deleted and never
freed.

Fixes: 71f28f3 ("ublk_drv: add io_uring based userspace block driver")
Cc: stable@kernel.org
Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
Every delete in the suite comes from a process that holds no reference on
the device, so none of them can wait on themselves. A server that deletes
its own device does: each command it has parked is a reference on its own
ublkc file, and those only go when it exits, which it cannot do until the
delete returns.

The verdict comes from three places, because the failure shows up in
different ones -- a server that never exits, a /dev/ublkcN that outlives
it, and a device number the next add cannot have. kublk gains --self_del
to reach the ordering at all.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
struct ublk_io kept struct io_uring_cmd *cmd and struct request *req in a
union.  Which of the two is in use is told by the flags
UBLK_IO_FLAG_ACTIVE and UBLK_IO_FLAG_OWNED_BY_SRV.  The two are never in
use at the same time, so the union is not wrong, but reading the right
member depends on checking the right flag, and there is no enforcement and
no sanity check.  Check the wrong flag, or none, and one gets a pointer to
the other type that still looks valid.  Earlier commits fixed two
instances of that same mistake:

 - "ublk: don't compare a tag that holds no command"
   ublk_belong_to_same_batch() read ->cmd without checking ACTIVE, and
   cancellation cleared ->cmd while leaving ACTIVE set
 - "ublk: end server-owned requests from the tagset"
   teardown read ->req for a state it had just tested

Split them into two fields and clear the one being left behind, in
__ublk_prep_compl_io_cmd() and ublk_fill_io_cmd().  The flags work as
before; what changes is that reading the wrong field now gives NULL, so a
mistake crashes right there instead of quietly using the wrong type.

struct ublk_io is ____cacheline_aligned_in_smp and had padding to spare,
so this costs no memory: the size stays 128 bytes here.

This is a hardening patch; it fixes no known bug on its own.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
Which of io->cmd and io->req is in use is told by io->flags, and reading
the wrong one now gives NULL rather than a pointer of the other type that
still looks valid. That is exactly what ublk/<dev_id>/tags prints, so the
invariant can be read straight off a running device.

Sampling while fio runs walks the tags through every state they take,
rather than catching them idle where only one field is ever set anyway.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
Every teardown case creates one device, tears it down and only then moves
on, so nothing covers a control command arriving from an unrelated process
while an abort walk is running. ublk_stop_dev() holds ublk_ctl_mutex across
del_gendisk(), so a teardown that does not finish blocks every device on
the machine and not only its own.

The verdict comes from three places, because a leak shows up in different
ones: a bounded add that never returns, a server or char device that
outlives its device, and a driver use count that does not fall back to what
it was before the device existed.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
The teardown cases all delete from an unrelated process, so the stop always
arrives from outside. A server that stops its own device while its queues
are still live is the other ordering a real server picks: it tells the
driver first and leaves its rings only once the queues drained.

The device is expected to go without any help -- the server exits on its
own, an add from another process does not queue behind it, and the delete
that follows does not wait.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
__ublk_fail_req() leaves the request on its last reference rather than
completing it, so whoever drops that reference does the disposition. For
an auto registered buffer the reference is held by io_uring and drops
only when the buffer is unregistered.

ublk_abort_dev() takes the tag from a live ublk server, clearing
UBLK_IO_FLAG_OWNED_BY_SRV. The server's next UBLK_IO_COMMIT_AND_FETCH_REQ
is then refused with -EBUSY before reaching ublk_clear_auto_buf_reg(), so
the buffer is never unregistered and the reference never drops:

    ublk_warn_started_rq: dev 0 qid 0 tag 0 still started:
                          io_flags 10 ref 1 task_bufs 0
      auto_reg  info 1                     task_registered_buffers = 1
      handover  granted 1                  server owns the tag
      set_canceling
      fail_req  info 0                     not completed, ref left at 1

del_gendisk() then waits in blk_mq_freeze_queue_wait() until the server
exits, which is what finally lets io_uring unregister the buffer.
ublk_ch_release_work_fn() has no such problem: it waits out active
references in ublk_check_and_reset_active_ref() first.

Unregister the buffer on the refused command. The refusal means the tag
is gone, and the server's io_ring_ctx is the only one that can release
what it registered.

Fixes: 5b0f1545e407 ("ublk: hold a request reference during daemon copies")
Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>

The cherry pick to 7.1-niova differs in respect to the unregister
call name: 7.1 exports io_buffer_unregister_bvec(). 51e08eaf954d
("io_uring/rsrc: rename io_buffer_register_bvec()/io_buffer_unregister_bvec()")
renamed it, and is not picked because it changes io_uring core.
Tag ownership is encoded in three independently set bits - ACTIVE,
DISPATCHING and OWNED_BY_SRV - written at about twenty sites. The
comments where they are defined describe a state machine ("Exclusive
with UBLK_IO_FLAG_ACTIVE", "Set alongside UBLK_IO_FLAG_ACTIVE"), but no
code enforces it, so a combination nobody intended is reached silently
and only shows up later, somewhere else.

Record the ownership state beside the flags and check it wherever it
changes. The flags still decide everything; ->state is only asked
whether a transition started where the caller believes it did, and a
mismatch names the tag, both states and the flags.

Callers that race another taker record without checking, because losing
that race is normal and already arbitrated by UBLK_IO_FLAG_CANCELED.
UBLK_F_BATCH_IO dispatches through the queue's fetch command rather than
a parked one, so its dispatch transition is recorded, not checked.

This is hardening. It found no bug in the paths it now covers; it makes
the next one report itself where it happens.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
Debug aid for the quiesce race; not for submission.

UBLK_CMD_QUIESCE_DEV can leave one tag holding a parked command that
nothing completes, so the server never exits and the device stays LIVE:

    tag 21 flags 0x00000001 ACTIVE cmd ffff888162091000 req 0 started 0

Which path put it there cannot be read off the state, because every
skip in ublk_cancel_cmd() delegates to a different owner and a last
value cannot show which side got there first.

Record the steps instead:

  - struct ublk_tag_evt, a ring of 16 per tag, stamped from one
    device-wide counter, written under io->lock
  - the last park kept out of the ring, which a requeue loop can age
    it out of
  - set_canceling_seq and the cancel_dev walk's start and end, so a
    tag's history can be placed against cancellation
  - cancel_skip_dispatch_parked: the walk skipped a tag that was
    holding a command, which is a tag it will not come back to
  - the ring is dumped for tags left ACTIVE with a command, the shape
    a stranded tag has

Two knobs widen one window each, in microseconds, default off, and
only while the queue is canceling, which is the only time the walk can
land in either. Both make the walk skip a tag holding a command:

  - delay_prep_cancel_us: between ublk_prep_req() marking the tag and
    __ublk_queue_rq_common() testing ->canceling. __ublk_abort_rq()
    ends that window and settles no command.
  - delay_park_check_us: between the command being parked by
    UBLK_IO_COMMIT_AND_FETCH_REQ and ublk_check_canceling() testing
    ->canceling, which does take the command back.

Only the first should be able to strand a tag.

Everything compiles out without CONFIG_DEBUG_FS.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>

The cherry pick to 7.1-niova differs in respect to one context line:
7.1 exports io_buffer_unregister_bvec(). 51e08eaf954d ("io_uring/rsrc:
rename io_buffer_register_bvec()/io_buffer_unregister_bvec()") renamed
it, and is not picked because it changes io_uring core. What this patch
adds is unchanged.
UBLK_IO_FLAG_ACTIVE is documented as "the io command is owned by ublk
driver", and UBLK_IO_FLAG_OWNED_BY_SRV as "Exclusive with
UBLK_IO_FLAG_ACTIVE: the command has been handed over, so io->cmd is
NULL". Both are stated where the flags are defined; neither is checked.

Callers rely on them. ublk_belong_to_same_batch() tests ACTIVE and then
passes io->cmd to io_uring_cmd_ctx_handle(), which dereferences it, and
__ublk_fetch() refuses a re-fetch on ACTIVE alone. A tag carrying ACTIVE
without a command therefore reaches code that cannot cope with it, and
cancellation did produce that combination.

Check the pair wherever it changes, under the lock that owns it, and
report the tag rather than only that something was wrong. This is
hardening: the combination is reachable, and nothing said so.

UBLK_F_BATCH_IO dispatches through the queue's fetch command instead of
a parked one, so its tags are ACTIVE without io->cmd and are skipped, as
__ublk_fail_req() already skips them for the same reason.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
test_generic_17.sh kills the recovery server mid-fetch and expects it to
die of SIGKILL. Whether it does is a race: kublk posts its ready
semaphore in __ublk_io_handler_fn() right after ublk_thread_init(), so
the main thread runs ahead to END_USER_RECOVERY while the queue thread
is still walking tags towards the tag 1 that raises SIGKILL. The queue
thread almost always wins, and the case where it loses is the one worth
testing.

Add --die_during_fetch_delay_us to let the kill be held back until
END_USER_RECOVERY is in the kernel, and a test that asserts the recover
command still exits. Default 0 keeps generic_17 as it was.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
The END_USER_RECOVERY deadlock needs the io-wq worker to reach
ublk_wait_dev_ready_and_lock() with SIGKILL already dequeued, which is
what get_signal() does for a PF_USER_WORKER before io_wq_worker() drains
the rest of its queue. Winning that race from user space is not
practical: the submit has to land between the kill being queued and the
worker draining.

Emulate the precondition instead. With the knob set the wait drops the
pending signal itself, which is deterministic and exercises exactly the
state the deadlock needs.

Debug only, drop before submission.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
A ublk server that dies before every queue has fetched all its I/O
commands can deadlock its own exit.

END_USER_RECOVERY and START_DEV both wait in
ublk_wait_dev_ready_and_lock() for ublk_dev_ready(), which needs
nr_io_ready == q_depth on every queue. Only the server can FETCH, so
once it is gone the condition is unreachable. Both commands may sleep,
so ublk_ctrl_uring_cmd() returns -EAGAIN for the inline issue and
io_uring always runs them from an io-wq worker. That worker is in the
server's own thread group, so do_exit() of the last user thread waits
for it in io_wq_put_and_exit() while it waits for a readiness that only
that thread group could deliver.

The wait is interruptible, which is what was meant to break this. It
does when the signal arrives while the worker already sleeps in the
wait. It does not when the worker picks the work up afterwards:
get_signal() dequeues SIGKILL for a PF_USER_WORKER and returns to the
worker instead of exiting it, and io_wq_worker() then drains the
remaining work with nothing pending. The wait sleeps with no signal to
end it and nothing to wake it - the only wake_up_var() on
->nr_queue_ready is on the ready path, and readiness only regresses
here.

Test the group exit state instead of relying on the signal. It is set
in complete_signal() before zap_other_threads() wakes anyone, and is
not cleared when the signal is dequeued, so a worker entering the wait
at any point after the server started dying sees it and gives up.

Found by test_generic_17.sh, which hangs rather than failing: the task
is stuck in D state, so its own kselftest timeout cannot kill it.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
ublk_batch_dispatch() checks ublk_io_evts_empty() twice without
ubq->evts_lock, while every producer bumps the fifo under it -
kfifo_put() in ublk_batch_queue_cmd(), kfifo_in() in
ublk_batch_queue_cmd_list(). KCSAN reports the pair:

  BUG: KCSAN: data-race in ublk_batch_dispatch / ublk_batch_queue_rq
  value changed: 0x0000012a -> 0x0000012b

The unlocked check is deliberate and safe. It is one half of a
store-buffer pair: the dispatcher clears ->active_fcmd, does smp_mb(),
then checks the fifo; the producer adds to the fifo, does smp_mb() in
__ublk_acquire_fcmd(), then checks ->active_fcmd. At least one side
observes the other's store, so the producer skipping the wakeup and the
dispatcher seeing an empty fifo cannot both happen, which is the case
that would strand a tag.

So the access wants marking, not locking. Both callers of the helper are
the unlocked ones, and ublk_io_evts_deinit() uses kfifo_is_empty()
directly, so marking it here covers the intended race and nothing else.

Found by KCSAN during test_teardown_batch_cancel_tw, which the report
fails.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
_ublk_wait_tag_flag_gone() greps the tags file for the flag name, so it
prints the one summary line that contains it. The per-tag event ring
prints below that line and carries io_flags values rather than flag
names, so the transitions that produced the stranded tag are dropped
exactly when a failure needs them.

teardown_refuse_handover is the case that wants this: it reports a tag
left OWNED_BY_SRV after the cancel pass, and the end state alone does
not say which path published it.

Print the matching tag together with the indented lines that follow it.

Assisted-by: Claude Opus 5
Signed-off-by: Bernd Schubert <bernd@niova.io>
ublk_clear_dispatching() read UBLK_IO_FLAG_DISPATCHING as the sign that
the tag was dispatching, but that flag outlives UBLK_IO_S_DISPATCHING:
ublk_queue_cmd_list() moved the state to UBLK_IO_S_TW_PENDING and left
the flag set across the task work hop.  Teardown took such a request
back through __ublk_abort_rq(), which overwrote UBLK_IO_S_TW_PENDING
with UBLK_IO_S_AVAILABLE, and the already queued ublk_cmd_tw_cb() then
warned in ublk_io_move().  io->state is verification only, so nothing
outside that warning changed.

Assisted-by: Claude Opus 5
All four callers capture __ublk_quiesce_dev() as state=$(...), but its
failure path passed the state to return, which takes a numeric exit
status.  bash rejected "LIVE" with "numeric argument required", so the
function printed nothing and _ublk_quiesce_and_recover() reported
"quiesce failed" instead of naming the state the device was left in.

Fixes: 533c87e ("selftests: ublk: add test for UBLK_F_QUIESCE")
Assisted-by: Claude Opus 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants