[PATCH 2/2] nvmet: pci-epf: complete failed read commands instead of waiting forever

From: shao.mingyin

Date: Tue Nov 03 2026 - 14:27:02 EST


nvmet_pci_epf_queue_response() completes a command directly when its
status is non-zero, without calling complete(&iod->done). For commands
that transfer data from the device to the host (DMA_TO_DEVICE),
nvmet_pci_epf_exec_iod_work() clears no_wait and waits for iod->done
after req->execute() has returned. If such a command fails
synchronously, for example because the request length or SGL is invalid
or because the backend rejects the command, the work item waits forever
on iod->done while the completion path has already queued the iod for
the completion queue work, which eventually frees it: the waiter is left
on a freed completion and the SQ worker is stuck.

Only decide whether the work item has to wait from the data direction
and length, and let it complete the command after the wait even when the
command failed. This preserves exactly one
nvmet_pci_epf_complete_iod() per command and also wakes the waiter for
failed read commands.

Fixes: 746d0ac5a07d ("nvmet: pci-epf: Do not complete commands twice if nvmet_req_init() fails")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---
diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index a8df176c1a57..b12855b57b59 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -1248,10 +1248,11 @@ static void nvmet_pci_epf_queue_response(struct nvmet_req *req)
iod->status = le16_to_cpu(req->cqe->status) >> 1;

/*
- * If the command failed or we have no data to transfer, complete the
- * command immediately.
+ * If we have no data to transfer back to the host, complete the
+ * command immediately. Otherwise wake up the work item, which
+ * transfers the data and completes the command even if it failed.
*/
- if (iod->status || !iod->data_len || iod->dma_dir != DMA_TO_DEVICE) {
+ if (!iod->data_len || iod->dma_dir != DMA_TO_DEVICE) {
nvmet_pci_epf_complete_iod(iod);
return;
}
@@ -1659,7 +1660,7 @@ static void nvmet_pci_epf_exec_iod_work(struct work_struct *work)
wait_for_completion(&iod->done);

if (iod->status != NVME_SC_SUCCESS)
- return;
+ goto complete;

WARN_ON_ONCE(!iod->data_len || iod->dma_dir != DMA_TO_DEVICE);
nvmet_pci_epf_transfer_iod_data(iod);