[PATCH 1/6] nvme-loop: release the target request when SG setup fails
From: shao.mingyin
Date: Tue Nov 10 2026 - 11:10:27 EST
From: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
nvme_loop_queue_rq() calls nvmet_req_init(), which takes a reference on
the submission queue percpu ref, pins the namespace and, for a
reservation-enabled namespace, takes a per-controller PR reference. If
sg_alloc_table_chained() then fails under memory pressure, the function
returns BLK_STS_RESOURCE without calling nvmet_req_uninit(). blk-mq
retries the same request and nvmet_req_init() overwrites req->ns and
req->pc_ref, leaking the queue, namespace and PR references taken by the
failed attempt each time this happens.
Release the request before returning BLK_STS_RESOURCE.
Fixes: 3a85a5de29ea ("nvme-loop: add a NVMe loopback host driver")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---
Tested on 7.3.0-next-20261030 (QEMU/TCG guest, 8 vCPUs) with the loop
transport and a file-backed namespace on tmpfs.
The scatterlist allocation was failed with failslab, narrowed to
nvme_loop_queue_rq() using the stack-trace filter. One request is not
enough: nvme-loop caps it at NVME_LOOP_MAX_SEGMENTS (256), i.e. two
128-entry chunks, and the sgpool mempool keeps two elements in reserve,
so the allocation only fails when several requests are in flight.
Eight concurrent 1020 KiB passthrough writes on /dev/ng0n1, with
non-contiguous pages so that every 4 KiB is its own scatterlist entry,
hit it; blk-mq then retries the same request.
unpatched patched
delete_controller write never returns completes in about 200 ms
blocked in nvmet_sq_destroy() -
The blocked task is in
nvmet_sq_destroy
nvme_loop_destroy_io_queues
nvme_loop_shutdown_ctrl
waiting for sq->confirm_done because the submission queue reference
was leaked. The failed attempt also leaks its namespace and any PR
reference when the retry overwrites the request fields.
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index e579a307798b..e95167a13708 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -159,6 +159,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
blk_rq_nr_phys_segments(req),
iod->sg_table.sgl, NVME_INLINE_SG_CNT)) {
nvme_cleanup_cmd(req);
+ nvmet_req_uninit(&iod->req);
return BLK_STS_RESOURCE;
}
--
2.27.0