From: Sagi Grimberg Date: Tue, 20 Jun 2023 13:07:36 +0000 (+0300) Subject: nvme-mpath: fix I/O failure with EAGAIN when failing over I/O X-Git-Tag: v6.5-rc1~63^2~1^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=99160af413b4ff1c3b4741e8a7583f8e7197f201;p=thirdparty%2Fkernel%2Flinux.git nvme-mpath: fix I/O failure with EAGAIN when failing over I/O It is possible that the next available path we failover to, happens to be frozen (for example if it is during connection establishment). If the original I/O was set with NOWAIT, this cause the I/O to unnecessarily fail because the request queue cannot be entered, hence the I/O fails with EAGAIN. The NOWAIT restriction that was originally set for the I/O is no longer relevant or needed because this is the nvme requeue context. Hence we clear the REQ_NOWAIT flag when failing over I/O. This fix a simple test case of nvme controller reset during I/O when the multipath device that has only a single path and I/O fails with "Resource temporarily unavailable" errno. Note that this reproduces with io_uring which by default sets IOCB_NOWAIT by default. Signed-off-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Signed-off-by: Keith Busch --- diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 91a9a55227fa3..3acb47760e246 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -106,6 +106,14 @@ void nvme_failover_req(struct request *req) bio->bi_opf &= ~REQ_POLLED; bio->bi_cookie = BLK_QC_T_NONE; } + /* + * The alternate request queue that we may end up submitting + * the bio to may be frozen temporarily, in this case REQ_NOWAIT + * will fail the I/O immediately with EAGAIN to the issuer. + * We are not in the issuer context which cannot block. Clear + * the flag to avoid spurious EAGAIN I/O failures. + */ + bio->bi_opf &= ~REQ_NOWAIT; } blk_steal_bios(&ns->head->requeue_list, req); spin_unlock_irqrestore(&ns->head->requeue_lock, flags);