Hannes Reinecke 329b5e
From: John Meneghini <johnm@netapp.com>
Hannes Reinecke 329b5e
Date: Thu, 20 Feb 2020 10:05:38 +0900
Hannes Reinecke 329b5e
Subject: [PATCH] nvme-multipath: do not reset on unknown status
Hannes Reinecke 329b5e
Git-commit: 764e9332098c0e60251386a507fe46ac91276120
Michal Kubecek 66e035
Patch-mainline: v5.7-rc1
Hannes Reinecke 329b5e
References: bsc#1161930
Hannes Reinecke 329b5e
Hannes Reinecke 329b5e
The nvme multipath error handling defaults to controller reset if the
Hannes Reinecke 329b5e
error is unknown. There are, however, no existing nvme status codes that
Hannes Reinecke 329b5e
indicate a reset should be used, and resetting causes unnecessary
Hannes Reinecke 329b5e
disruption to the rest of IO.
Hannes Reinecke 329b5e
Hannes Reinecke 329b5e
Change nvme's error handling to first check if failover should happen.
Hannes Reinecke 329b5e
If not, let the normal error handling take over rather than reset the
Hannes Reinecke 329b5e
controller.
Hannes Reinecke 329b5e
Hannes Reinecke 329b5e
Based-on-a-patch-by: Christoph Hellwig <hch@lst.de>
Hannes Reinecke 329b5e
Reviewed-by: Hannes Reinecke <hare@suse.de>
Hannes Reinecke 329b5e
Signed-off-by: John Meneghini <johnm@netapp.com>
Hannes Reinecke 329b5e
Signed-off-by: Keith Busch <kbusch@kernel.org>
Hannes Reinecke 329b5e
Acked-by: Hannes Reinecke <hare@suse.com>
Hannes Reinecke 329b5e
---
Hannes Reinecke 329b5e
 drivers/nvme/host/core.c      |  5 +----
Hannes Reinecke 329b5e
 drivers/nvme/host/multipath.c | 21 +++++++++------------
Hannes Reinecke 329b5e
 drivers/nvme/host/nvme.h      |  5 +++--
Hannes Reinecke 329b5e
 3 files changed, 13 insertions(+), 18 deletions(-)
Hannes Reinecke 329b5e
Hannes Reinecke 329b5e
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
Hannes Reinecke 329b5e
index 0e38e07a302f..fde4b3a526ad 100644
Hannes Reinecke 329b5e
--- a/drivers/nvme/host/core.c
Hannes Reinecke 329b5e
+++ b/drivers/nvme/host/core.c
Hannes Reinecke 329b5e
@@ -291,11 +291,8 @@ void nvme_complete_rq(struct request *req)
Hannes Reinecke 329b5e
 		nvme_req(req)->ctrl->comp_seen = true;
Hannes Reinecke 329b5e
 
Hannes Reinecke 329b5e
 	if (unlikely(status != BLK_STS_OK && nvme_req_needs_retry(req))) {
Hannes Reinecke 329b5e
-		if ((req->cmd_flags & REQ_NVME_MPATH) &&
Hannes Reinecke 329b5e
-		    blk_path_error(status)) {
Hannes Reinecke 329b5e
-			nvme_failover_req(req);
Hannes Reinecke 329b5e
+		if ((req->cmd_flags & REQ_NVME_MPATH) && nvme_failover_req(req))
Hannes Reinecke 329b5e
 			return;
Hannes Reinecke 329b5e
-		}
Hannes Reinecke 329b5e
 
Hannes Reinecke 329b5e
 		if (!blk_queue_dying(req->q)) {
Hannes Reinecke 329b5e
 			nvme_retry_req(req);
Hannes Reinecke 329b5e
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
Hannes Reinecke 329b5e
index a11900cf3a36..90dd1d641b7b 100644
Hannes Reinecke 329b5e
--- a/drivers/nvme/host/multipath.c
Hannes Reinecke 329b5e
+++ b/drivers/nvme/host/multipath.c
Hannes Reinecke 329b5e
@@ -64,17 +64,12 @@ void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
Hannes Reinecke 329b5e
 	}
Hannes Reinecke 329b5e
 }
Hannes Reinecke 329b5e
 
Hannes Reinecke 329b5e
-void nvme_failover_req(struct request *req)
Hannes Reinecke 329b5e
+bool nvme_failover_req(struct request *req)
Hannes Reinecke 329b5e
 {
Hannes Reinecke 329b5e
 	struct nvme_ns *ns = req->q->queuedata;
Hannes Reinecke 329b5e
 	u16 status = nvme_req(req)->status;
Hannes Reinecke 329b5e
 	unsigned long flags;
Hannes Reinecke 329b5e
 
Hannes Reinecke 329b5e
-	spin_lock_irqsave(&ns->head->requeue_lock, flags);
Hannes Reinecke 329b5e
-	blk_steal_bios(&ns->head->requeue_list, req);
Hannes Reinecke 329b5e
-	spin_unlock_irqrestore(&ns->head->requeue_lock, flags);
Hannes Reinecke 329b5e
-	blk_mq_end_request(req, 0);
Hannes Reinecke 329b5e
-
Hannes Reinecke 329b5e
 	switch (status & 0x7ff) {
Hannes Reinecke 329b5e
 	case NVME_SC_ANA_TRANSITION:
Hannes Reinecke 329b5e
 	case NVME_SC_ANA_INACCESSIBLE:
Hannes Reinecke 329b5e
@@ -103,15 +98,17 @@ void nvme_failover_req(struct request *req)
Hannes Reinecke 329b5e
 		nvme_mpath_clear_current_path(ns);
Hannes Reinecke 329b5e
 		break;
Hannes Reinecke 329b5e
 	default:
Hannes Reinecke 329b5e
-		/*
Hannes Reinecke 329b5e
-		 * Reset the controller for any non-ANA error as we don't know
Hannes Reinecke 329b5e
-		 * what caused the error.
Hannes Reinecke 329b5e
-		 */
Hannes Reinecke 329b5e
-		nvme_reset_ctrl(ns->ctrl);
Hannes Reinecke 329b5e
-		break;
Hannes Reinecke 329b5e
+		/* This was a non-ANA error so follow the normal error path. */
Hannes Reinecke 329b5e
+		return false;
Hannes Reinecke 329b5e
 	}
Hannes Reinecke 329b5e
 
Hannes Reinecke 329b5e
+	spin_lock_irqsave(&ns->head->requeue_lock, flags);
Hannes Reinecke 329b5e
+	blk_steal_bios(&ns->head->requeue_list, req);
Hannes Reinecke 329b5e
+	spin_unlock_irqrestore(&ns->head->requeue_lock, flags);
Hannes Reinecke 329b5e
+	blk_mq_end_request(req, 0);
Hannes Reinecke 329b5e
+
Hannes Reinecke 329b5e
 	kblockd_schedule_work(&ns->head->requeue_work);
Hannes Reinecke 329b5e
+	return true;
Hannes Reinecke 329b5e
 }
Hannes Reinecke 329b5e
 
Hannes Reinecke 329b5e
 void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
Hannes Reinecke 329b5e
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
Hannes Reinecke 329b5e
index 1024fec7914c..d800b9a51c2c 100644
Hannes Reinecke 329b5e
--- a/drivers/nvme/host/nvme.h
Hannes Reinecke 329b5e
+++ b/drivers/nvme/host/nvme.h
Hannes Reinecke 329b5e
@@ -550,7 +550,7 @@ void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys);
Hannes Reinecke 329b5e
 void nvme_mpath_start_freeze(struct nvme_subsystem *subsys);
Hannes Reinecke 329b5e
 void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
Hannes Reinecke 329b5e
 			struct nvme_ctrl *ctrl, int *flags);
Hannes Reinecke 329b5e
-void nvme_failover_req(struct request *req);
Hannes Reinecke 329b5e
+bool nvme_failover_req(struct request *req);
Hannes Reinecke 329b5e
 void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl);
Hannes Reinecke 329b5e
 int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl,struct nvme_ns_head *head);
Hannes Reinecke 329b5e
 void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id);
Hannes Reinecke 329b5e
@@ -599,8 +599,9 @@ static inline void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
Hannes Reinecke 329b5e
 	sprintf(disk_name, "nvme%dn%d", ctrl->instance, ns->head->instance);
Hannes Reinecke 329b5e
 }
Hannes Reinecke 329b5e
 
Hannes Reinecke 329b5e
-static inline void nvme_failover_req(struct request *req)
Hannes Reinecke 329b5e
+static inline bool nvme_failover_req(struct request *req)
Hannes Reinecke 329b5e
 {
Hannes Reinecke 329b5e
+	return false;
Hannes Reinecke 329b5e
 }
Hannes Reinecke 329b5e
 static inline void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
Hannes Reinecke 329b5e
 {
Hannes Reinecke 329b5e
-- 
Hannes Reinecke 329b5e
2.16.4
Hannes Reinecke 329b5e