ublk: fix dead loop when canceling io command
authorMing Lei <ming.lei@redhat.com>
Thu, 15 May 2025 16:26:01 +0000 (00:26 +0800)
committerJens Axboe <axboe@kernel.dk>
Thu, 15 May 2025 16:53:41 +0000 (10:53 -0600)
Commit:

f40139fde527 ("ublk: fix race between io_uring_cmd_complete_in_task and
ublk_cancel_cmd")

adds a request state check in ublk_cancel_cmd(), and if the request is
started, skips canceling this uring_cmd.

However, the current uring_cmd may be in ACTIVE state, without block
request coming to the uring command. Meantime, if the cached request in
tag_set.tags[tag] has been delivered to ublk server and reycycled, then
this uring_cmd can't be canceled.

ublk requests are aborted in ublk char device release handler, which
depends on canceling all ACTIVE uring_cmd. So it causes a dead loop.

Fix this issue by not taking a stale request into account when canceling
uring_cmd in ublk_cancel_cmd().

Reported-by: Shinichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Closes: https://lore.kernel.org/linux-block/mruqwpf4tqenkbtgezv5oxwq7ngyq24jzeyqy4ixzvivatbbxv@4oh2wzz4e6qn/
Fixes: f40139fde527 ("ublk: fix race between io_uring_cmd_complete_in_task and ublk_cancel_cmd")
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20250515162601.77346-1-ming.lei@redhat.com
[axboe: rewording of commit message]
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/ublk_drv.c

index f903207..dc104c0 100644 (file)
@@ -1708,7 +1708,7 @@ static void ublk_cancel_cmd(struct ublk_queue *ubq, unsigned tag,
         * that ublk_dispatch_req() is always called
         */
        req = blk_mq_tag_to_rq(ub->tag_set.tags[ubq->q_id], tag);
-       if (req && blk_mq_request_started(req))
+       if (req && blk_mq_request_started(req) && req->tag == tag)
                return;
 
        spin_lock(&ubq->cancel_lock);