]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
nvme-multipath: do not reset on unknown status
authorJohn Meneghini <johnm@netapp.com>
Thu, 20 Feb 2020 01:05:38 +0000 (10:05 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 1 Oct 2020 11:14:40 +0000 (13:14 +0200)
[ Upstream commit 764e9332098c0e60251386a507fe46ac91276120 ]

The nvme multipath error handling defaults to controller reset if the
error is unknown. There are, however, no existing nvme status codes that
indicate a reset should be used, and resetting causes unnecessary
disruption to the rest of IO.

Change nvme's error handling to first check if failover should happen.
If not, let the normal error handling take over rather than reset the
controller.

Based-on-a-patch-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: John Meneghini <johnm@netapp.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/nvme.h

index 0d60f2f8f3eecf8f33e045e20a15204e92108ef0..4b182ac15687e4dfce3b7365714f918f0ae5deee 100644 (file)
@@ -255,11 +255,8 @@ void nvme_complete_rq(struct request *req)
        trace_nvme_complete_rq(req);
 
        if (unlikely(status != BLK_STS_OK && nvme_req_needs_retry(req))) {
-               if ((req->cmd_flags & REQ_NVME_MPATH) &&
-                   blk_path_error(status)) {
-                       nvme_failover_req(req);
+               if ((req->cmd_flags & REQ_NVME_MPATH) && nvme_failover_req(req))
                        return;
-               }
 
                if (!blk_queue_dying(req->q)) {
                        nvme_req(req)->retries++;
index 2e63c1106030b9b83772e94e55aef8ba4495b7e7..e71075338ff5c1346c99492155724f465ad5babf 100644 (file)
@@ -73,17 +73,12 @@ void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
        }
 }
 
-void nvme_failover_req(struct request *req)
+bool nvme_failover_req(struct request *req)
 {
        struct nvme_ns *ns = req->q->queuedata;
        u16 status = nvme_req(req)->status;
        unsigned long flags;
 
-       spin_lock_irqsave(&ns->head->requeue_lock, flags);
-       blk_steal_bios(&ns->head->requeue_list, req);
-       spin_unlock_irqrestore(&ns->head->requeue_lock, flags);
-       blk_mq_end_request(req, 0);
-
        switch (status & 0x7ff) {
        case NVME_SC_ANA_TRANSITION:
        case NVME_SC_ANA_INACCESSIBLE:
@@ -111,15 +106,17 @@ void nvme_failover_req(struct request *req)
                nvme_mpath_clear_current_path(ns);
                break;
        default:
-               /*
-                * Reset the controller for any non-ANA error as we don't know
-                * what caused the error.
-                */
-               nvme_reset_ctrl(ns->ctrl);
-               break;
+               /* This was a non-ANA error so follow the normal error path. */
+               return false;
        }
 
+       spin_lock_irqsave(&ns->head->requeue_lock, flags);
+       blk_steal_bios(&ns->head->requeue_list, req);
+       spin_unlock_irqrestore(&ns->head->requeue_lock, flags);
+       blk_mq_end_request(req, 0);
+
        kblockd_schedule_work(&ns->head->requeue_work);
+       return true;
 }
 
 void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
index cc4273f1198943867e6dc0388af18dcd3f0fff1e..31c1496f938fb70a0c12b2f4660a1b943657feae 100644 (file)
@@ -477,7 +477,7 @@ void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys);
 void nvme_mpath_start_freeze(struct nvme_subsystem *subsys);
 void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
                        struct nvme_ctrl *ctrl, int *flags);
-void nvme_failover_req(struct request *req);
+bool nvme_failover_req(struct request *req);
 void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl);
 int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl,struct nvme_ns_head *head);
 void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id);
@@ -521,8 +521,9 @@ static inline void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
        sprintf(disk_name, "nvme%dn%d", ctrl->instance, ns->head->instance);
 }
 
-static inline void nvme_failover_req(struct request *req)
+static inline bool nvme_failover_req(struct request *req)
 {
+       return false;
 }
 static inline void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
 {