Skip to content

Commit d85473b

Browse files
axboegregkh
authored andcommitted
nvme: always punt polled uring_cmd end_io work to task_work
Commit 9ce6c9875f3e995be5fd720b65835291f8a609b1 upstream. Currently NVMe uring_cmd completions will complete locally, if they are polled. This is done because those completions are always invoked from task context. And while that is true, there's no guarantee that it's invoked under the right ring context, or even task. If someone does NVMe passthrough via multiple threads and with a limited number of poll queues, then ringA may find completions from ringB. For that case, completing the request may not be sound. Always just punt the passthrough completions via task_work, which will redirect the completion, if needed. Cc: [email protected] Fixes: 585079b ("nvme: wire up async polling for io passthrough commands") Signed-off-by: Jens Axboe <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent b80d171 commit d85473b

File tree

1 file changed

+7
-8
lines changed

1 file changed

+7
-8
lines changed

drivers/nvme/host/ioctl.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,6 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
438438
{
439439
struct io_uring_cmd *ioucmd = req->end_io_data;
440440
struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
441-
void *cookie = READ_ONCE(ioucmd->cookie);
442441

443442
req->bio = pdu->bio;
444443
if (nvme_req(req)->flags & NVME_REQ_CANCELLED) {
@@ -451,14 +450,14 @@ static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
451450
pdu->u.result = le64_to_cpu(nvme_req(req)->result.u64);
452451

453452
/*
454-
* For iopoll, complete it directly.
455-
* Otherwise, move the completion to task work.
453+
* IOPOLL could potentially complete this request directly, but
454+
* if multiple rings are polling on the same queue, then it's possible
455+
* for one ring to find completions for another ring. Punting the
456+
* completion via task_work will always direct it to the right
457+
* location, rather than potentially complete requests for ringA
458+
* under iopoll invocations from ringB.
456459
*/
457-
if (cookie != NULL && blk_rq_is_poll(req))
458-
nvme_uring_task_cb(ioucmd, IO_URING_F_UNLOCKED);
459-
else
460-
io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_cb);
461-
460+
io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_cb);
462461
return RQ_END_IO_FREE;
463462
}
464463

0 commit comments

Comments
 (0)