[PATCH 4/4] nvme: harden local IOPOLL user copyback

王 颖杰 x-professor at outlook.com
Thu Oct 15 23:19:37 PDT 2026


The local NVMe IOPOLL completion path performs blk_rq_unmap_user()
inline, ignores a possible copyback failure, and relies on the block
layer to free the request only after the callback returns.

Free the completed request explicitly before touching userspace, return
RQ_END_IO_NONE to transfer that ownership, and report an unmap error
when no earlier command error exists.  This keeps the inline path
consistent with task-work completion without adding task-work overhead.

The completion PDU is stored in io_uring_cmd rather than the request,
so its saved bio, status, and result remain valid after
blk_mq_free_request().

With a real NVMe poll queue and the task-work path already fixed,
1,280/1,280 commands into an unaligned PROT_NONE destination still
posted success before this change.  All 1,280 posted -EFAULT afterward,
while writable controls remained successful.

Fixes: f7bc22ca0d55 ("nvme/io_uring: optimize IOPOLL completions for local ring context")
Cc: stable at vger.kernel.org
Assisted-by: LLM
Signed-off-by: Yingjie Wang <x-professor at outlook.com>
---
 drivers/nvme/host/ioctl.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 06c3f3232ba..e4ea30e9129 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -474,12 +474,18 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
 	 */
 	if (blk_rq_is_poll(req) && iob &&
 	    iob->poll_ctx == io_uring_cmd_ctx_handle(ioucmd)) {
+		int ret = 0;
+
+		blk_mq_free_request(req);
 		if (pdu->bio)
-			blk_rq_unmap_user(pdu->bio);
+			ret = blk_rq_unmap_user(pdu->bio);
+		if (!pdu->status)
+			pdu->status = ret;
 		io_uring_cmd_done32(ioucmd, pdu->status, pdu->result, 0);
-	} else {
-		io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb);
+		return RQ_END_IO_NONE;
 	}
+
+	io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb);
 	return RQ_END_IO_FREE;
 }
 
-- 
2.43.0



More information about the Linux-nvme mailing list