From 4915dc0a1834457520ef0592bfd454b26901614f Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 11 Oct 2026 01:35:49 -0500 Subject: [PATCH] ublk: allow a NULL io->cmd in the cancel callback A cancel from the control path, like STOP_DEV's ublk_cancel_dev() after dropping ub->mutex, takes the command and clears io->cmd under cancel_lock, then completes it with io_uring_cmd_done(), which takes uring_lock to remove it from the cancelable list. The server's io_uring cancel runs ublk_uring_cmd_cancel_fn() under uring_lock in between: control path cancel io_uring cancel (uring_lock) io->cmd = NULL, CANCELED io_uring_cmd_done() waits for uring_lock cmd still on the list ublk_uring_cmd_cancel_fn(cmd) io->cmd == NULL: WARN ublk_cancel_cmd() then sees CANCELED and leaves the command alone, so nothing is wrong; only warn if io->cmd holds another command. Fixes: ab03a61c6614 ("ublk: have a per-io daemon instead of a per-queue daemon") Tested-by: Josef Bacik Signed-off-by: Ming Lei Link: https://patch.msgid.link/20261011063555.1142277-7-tom.leiming@gmail.com Signed-off-by: Jens Axboe --- drivers/block/ublk_drv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index 004570cf44c5..c0a112a9bf42 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -2896,6 +2896,7 @@ static void ublk_uring_cmd_cancel_fn(struct io_uring_cmd *cmd, { struct ublk_uring_cmd_pdu *pdu = ublk_get_uring_cmd_pdu(cmd); struct ublk_queue *ubq = pdu->ubq; + struct io_uring_cmd *cur; struct task_struct *task; struct ublk_io *io; @@ -2912,7 +2913,9 @@ static void ublk_uring_cmd_cancel_fn(struct io_uring_cmd *cmd, ublk_start_cancel(ubq->dev); - WARN_ON_ONCE(io->cmd != cmd); + /* NULL if a cancel from the control path took it meanwhile */ + cur = READ_ONCE(io->cmd); + WARN_ON_ONCE(cur && cur != cmd); ublk_cancel_cmd(ubq, pdu->tag, issue_flags); }