From: keith.busch@intel.com (Keith Busch)
Subject: [PATCHv2 3/8] nvme: Move all IO out of controller reset
Date: Tue, 22 May 2018 16:03:27 -0600 [thread overview]
Message-ID: <20180522220332.9244-4-keith.busch@intel.com> (raw)
In-Reply-To: <20180522220332.9244-1-keith.busch@intel.com>
IO may be retryable, so don't wait for them in the reset path. These
commands may trigger a reset if that IO expires without a completion,
placing it on the requeue list. Waiting for these would then deadlock
the reset handler.
To fix the theoretical deadlock, this patch unblocks IO submission from
the reset_work when we enter the LIVE state as before, but moves the
waiting to the IO safe scan_work so that the reset_work may proceed to
completion. Since the unfreezing happens in the controller LIVE state,
the nvme device has to track if the queues were frozen now to prevent
incorrect freeze depths.
This patch is also renaming the function 'nvme_dev_add' to a
more appropriate name that describes what it's actually doing:
nvme_alloc_io_tags.
Signed-off-by: Keith Busch <keith.busch at intel.com>
---
drivers/nvme/host/core.c | 2 ++
drivers/nvme/host/nvme.h | 1 +
drivers/nvme/host/pci.c | 46 +++++++++++++++++++++++++++++++---------------
3 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 1de68b56b318..1f34f1169dbd 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3177,6 +3177,8 @@ static void nvme_scan_work(struct work_struct *work)
struct nvme_id_ctrl *id;
unsigned nn;
+ if (ctrl->ops->update_hw_ctx)
+ ctrl->ops->update_hw_ctx(ctrl);
if (ctrl->state != NVME_CTRL_LIVE)
return;
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index c15c2ee7f61a..230c5424b197 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -320,6 +320,7 @@ struct nvme_ctrl_ops {
int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
int (*reinit_request)(void *data, struct request *rq);
void (*stop_ctrl)(struct nvme_ctrl *ctrl);
+ void (*update_hw_ctx)(struct nvme_ctrl *ctrl);
};
#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 8949ea3609d8..5de8d79bad20 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -99,6 +99,7 @@ struct nvme_dev {
u32 cmbloc;
struct nvme_ctrl ctrl;
struct completion ioq_wait;
+ bool queues_froze;
/* shadow doorbell buffer support: */
u32 *dbbuf_dbs;
@@ -2065,10 +2066,32 @@ static void nvme_disable_io_queues(struct nvme_dev *dev)
}
}
+static void nvme_pci_update_hw_ctx(struct nvme_ctrl *ctrl)
+{
+ struct nvme_dev *dev = to_nvme_dev(ctrl);
+ bool unfreeze;
+
+ mutex_lock(&dev->shutdown_lock);
+ unfreeze = dev->queues_froze;
+ mutex_unlock(&dev->shutdown_lock);
+
+ if (!unfreeze)
+ return;
+
+ nvme_wait_freeze(&dev->ctrl);
+ blk_mq_update_nr_hw_queues(ctrl->tagset, dev->online_queues - 1);
+ nvme_free_queues(dev, dev->online_queues);
+ nvme_unfreeze(&dev->ctrl);
+
+ mutex_lock(&dev->shutdown_lock);
+ dev->queues_froze = false;
+ mutex_unlock(&dev->shutdown_lock);
+}
+
/*
* return error value only when tagset allocation failed
*/
-static int nvme_dev_add(struct nvme_dev *dev)
+static int nvme_alloc_io_tags(struct nvme_dev *dev)
{
int ret;
@@ -2096,13 +2119,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
dev->ctrl.tagset = &dev->tagset;
nvme_dbbuf_set(dev);
- } else {
- blk_mq_update_nr_hw_queues(&dev->tagset, dev->online_queues - 1);
-
- /* Free previously allocated queues that are no longer usable */
- nvme_free_queues(dev, dev->online_queues);
}
-
return 0;
}
@@ -2201,7 +2218,10 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
dev->ctrl.state == NVME_CTRL_RESETTING)) {
u32 csts = readl(dev->bar + NVME_REG_CSTS);
- nvme_start_freeze(&dev->ctrl);
+ if (!dev->queues_froze) {
+ nvme_start_freeze(&dev->ctrl);
+ dev->queues_froze = true;
+ }
dead = !!((csts & NVME_CSTS_CFS) || !(csts & NVME_CSTS_RDY) ||
pci_channel_offline(pdev) || !pci_is_enabled(pdev));
}
@@ -2379,13 +2399,8 @@ static void nvme_reset_work(struct work_struct *work)
nvme_kill_queues(&dev->ctrl);
nvme_remove_namespaces(&dev->ctrl);
new_state = NVME_CTRL_ADMIN_ONLY;
- } else {
- nvme_start_queues(&dev->ctrl);
- nvme_wait_freeze(&dev->ctrl);
- /* hit this only when allocate tagset fails */
- if (nvme_dev_add(dev))
- new_state = NVME_CTRL_ADMIN_ONLY;
- nvme_unfreeze(&dev->ctrl);
+ } else if (nvme_alloc_io_tags(dev)) {
+ new_state = NVME_CTRL_ADMIN_ONLY;
}
/*
@@ -2450,6 +2465,7 @@ static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
.reg_read64 = nvme_pci_reg_read64,
.free_ctrl = nvme_pci_free_ctrl,
.submit_async_event = nvme_pci_submit_async_event,
+ .update_hw_ctx = nvme_pci_update_hw_ctx,
.get_address = nvme_pci_get_address,
};
--
2.14.3
next prev parent reply other threads:[~2018-05-22 22:03 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-05-22 22:03 [PATCHv2 0/8] nvme timeout fixes v2 Keith Busch
2018-05-22 22:03 ` [PATCHv2 1/8] nvme: Sync request queues on reset Keith Busch
2018-05-22 22:03 ` [PATCHv2 2/8] nvme-pci: Fix queue freeze criteria " Keith Busch
2018-05-22 22:03 ` Keith Busch [this message]
2018-05-22 22:03 ` [PATCHv2 4/8] nvme: Allow reset from CONNECTING state Keith Busch
2018-05-22 22:03 ` [PATCHv2 5/8] nvme-pci: Attempt reset retry for IO failures Keith Busch
2018-05-22 22:03 ` [PATCHv2 6/8] nvme-pci: Rate limit the nvme timeout warnings Keith Busch
2018-05-22 22:03 ` [PATCHv2 7/8] nvme-pci: End IO requests in CONNECTING state Keith Busch
2018-05-22 22:03 ` [PATCHv2 8/8] nvme-pci: Unquiesce queues on dead controller Keith Busch
2018-05-23 3:00 ` [PATCHv2 0/8] nvme timeout fixes v2 Ming Lei
2018-05-23 16:16 ` Keith Busch
2018-05-23 22:49 ` Keith Busch
2018-05-24 6:52 ` jianchao.wang
2018-07-11 23:23 ` James Smart
2018-05-24 3:23 ` Ming Lei
2018-05-24 13:57 ` Keith Busch
2018-05-24 15:04 ` Ming Lei
2018-05-24 15:16 ` Keith Busch
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180522220332.9244-4-keith.busch@intel.com \
--to=keith.busch@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).