1 |
From f809772d40dc7774cd047140bc0919c80ad521e7 Mon Sep 17 00:00:00 2001 |
2 |
From: James Smart <jsmart2021@gmail.com> |
3 |
Date: Thu, 27 Sep 2018 16:58:54 -0700 |
4 |
Subject: [PATCH 039/145] nvme: call nvme_complete_rq when nvmf_check_ready |
5 |
fails for mpath I/O |
6 |
|
7 |
[ Upstream commit 783f4a4408e1251d17f333ad56abac24dde988b9 ] |
8 |
|
9 |
When an io is rejected by nvmf_check_ready() due to validation of the |
10 |
controller state, the nvmf_fail_nonready_command() will normally return |
11 |
BLK_STS_RESOURCE to requeue and retry. However, if the controller is |
12 |
dying or the I/O is marked for NVMe multipath, the I/O is failed so that |
13 |
the controller can terminate or so that the io can be issued on a |
14 |
different path. Unfortunately, as this reject point is before the |
15 |
transport has accepted the command, blk-mq ends up completing the I/O |
16 |
and never calls nvme_complete_rq(), which is where multipath may preserve |
17 |
or re-route the I/O. The end result is, the device user ends up seeing an |
18 |
EIO error. |
19 |
|
20 |
Example: single path connectivity, controller is under load, and a reset |
21 |
is induced. An I/O is received: |
22 |
|
23 |
a) while the reset state has been set but the queues have yet to be |
24 |
stopped; or |
25 |
b) after queues are started (at end of reset) but before the reconnect |
26 |
has completed. |
27 |
|
28 |
The I/O finishes with an EIO status. |
29 |
|
30 |
This patch makes the following changes: |
31 |
|
32 |
- Adds the HOST_PATH_ERROR pathing status from TP4028 |
33 |
- Modifies the reject point such that it appears to queue successfully, |
34 |
but actually completes the io with the new pathing status and calls |
35 |
nvme_complete_rq(). |
36 |
- nvme_complete_rq() recognizes the new status, avoids resetting the |
37 |
controller (likely was already done in order to get this new status), |
38 |
and calls the multipather to clear the current path that errored. |
39 |
This allows the next command (retry or new command) to select a new |
40 |
path if there is one. |
41 |
|
42 |
Signed-off-by: James Smart <jsmart2021@gmail.com> |
43 |
Reviewed-by: Sagi Grimberg <sagi@grimberg.me> |
44 |
Signed-off-by: Christoph Hellwig <hch@lst.de> |
45 |
Signed-off-by: Sasha Levin <sashal@kernel.org> |
46 |
--- |
47 |
drivers/nvme/host/fabrics.c | 7 +++++-- |
48 |
drivers/nvme/host/multipath.c | 7 +++++++ |
49 |
include/linux/nvme.h | 1 + |
50 |
3 files changed, 13 insertions(+), 2 deletions(-) |
51 |
|
52 |
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c |
53 |
index 206d63cb1afc..bcd09d3a44da 100644 |
54 |
--- a/drivers/nvme/host/fabrics.c |
55 |
+++ b/drivers/nvme/host/fabrics.c |
56 |
@@ -552,8 +552,11 @@ blk_status_t nvmf_fail_nonready_command(struct nvme_ctrl *ctrl, |
57 |
ctrl->state != NVME_CTRL_DEAD && |
58 |
!blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH)) |
59 |
return BLK_STS_RESOURCE; |
60 |
- nvme_req(rq)->status = NVME_SC_ABORT_REQ; |
61 |
- return BLK_STS_IOERR; |
62 |
+ |
63 |
+ nvme_req(rq)->status = NVME_SC_HOST_PATH_ERROR; |
64 |
+ blk_mq_start_request(rq); |
65 |
+ nvme_complete_rq(rq); |
66 |
+ return BLK_STS_OK; |
67 |
} |
68 |
EXPORT_SYMBOL_GPL(nvmf_fail_nonready_command); |
69 |
|
70 |
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c |
71 |
index 9fe3fff818b8..b71c9ad1bf45 100644 |
72 |
--- a/drivers/nvme/host/multipath.c |
73 |
+++ b/drivers/nvme/host/multipath.c |
74 |
@@ -77,6 +77,13 @@ void nvme_failover_req(struct request *req) |
75 |
queue_work(nvme_wq, &ns->ctrl->ana_work); |
76 |
} |
77 |
break; |
78 |
+ case NVME_SC_HOST_PATH_ERROR: |
79 |
+ /* |
80 |
+ * Temporary transport disruption in talking to the controller. |
81 |
+ * Try to send on a new path. |
82 |
+ */ |
83 |
+ nvme_mpath_clear_current_path(ns); |
84 |
+ break; |
85 |
default: |
86 |
/* |
87 |
* Reset the controller for any non-ANA error as we don't know |
88 |
diff --git a/include/linux/nvme.h b/include/linux/nvme.h |
89 |
index 68e91ef5494c..818dbe9331be 100644 |
90 |
--- a/include/linux/nvme.h |
91 |
+++ b/include/linux/nvme.h |
92 |
@@ -1241,6 +1241,7 @@ enum { |
93 |
NVME_SC_ANA_PERSISTENT_LOSS = 0x301, |
94 |
NVME_SC_ANA_INACCESSIBLE = 0x302, |
95 |
NVME_SC_ANA_TRANSITION = 0x303, |
96 |
+ NVME_SC_HOST_PATH_ERROR = 0x370, |
97 |
|
98 |
NVME_SC_DNR = 0x4000, |
99 |
}; |
100 |
-- |
101 |
2.19.1 |
102 |
|