>From a9bfa1edc7566bdaac8d330cd813fe2c0d0728cb Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 1 Oct 2020 10:52:27 +0200 Subject: [PATCH] nvme: move FAILFAST_EXPIRED bit into namespace Rather than having the FAILFAST_EXPIRED bit being a flag on the controller move it into the namespace. This allows the failfast mechanism to cover ANA states, too, which might indicate that I/O isn't possible despite the controller being LIVE. Signed-off-by: Hannes Reinecke --- drivers/nvme/host/core.c | 26 ++++++++++++++++---------- drivers/nvme/host/fabrics.c | 4 +++- drivers/nvme/host/multipath.c | 11 ++++++----- drivers/nvme/host/nvme.h | 3 +-- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 0d571aa3cc97..b458508b0c91 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -151,12 +151,16 @@ EXPORT_SYMBOL_GPL(nvme_try_sched_reset); static void nvme_failfast_work(struct work_struct *work) { struct nvme_ctrl *ctrl = container_of(to_delayed_work(work), struct nvme_ctrl, failfast_work); + struct nvme_ns *ns; - if (ctrl->state != NVME_CTRL_CONNECTING) - return; - - - set_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags); + down_read(&ctrl->namespaces_rwsem); + list_for_each_entry(ns, &ctrl->namespaces, list) { + if (ctrl->state != NVME_CTRL_LIVE || + (ns->ana_state != NVME_ANA_OPTIMIZED && + ns->ana_state != NVME_ANA_NONOPTIMIZED)) + set_bit(NVME_NS_FAILFAST_EXPIRED, &ns->flags); + } + up_read(&ctrl->namespaces_rwsem); dev_info(ctrl->device, "failfast expired\n"); nvme_kick_requeue_lists(ctrl); } @@ -172,11 +176,16 @@ static inline void nvme_start_failfast_work(struct nvme_ctrl *ctrl) static inline void nvme_stop_failfast_work(struct nvme_ctrl *ctrl) { + struct nvme_ns *ns; + if (!ctrl->opts) return; cancel_delayed_work_sync(&ctrl->failfast_work); - clear_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags); + down_read(&ctrl->namespaces_rwsem); + list_for_each_entry(ns, &ctrl->namespaces, list) + clear_bit(NVME_NS_FAILFAST_EXPIRED, &ns->flags); + up_read(&ctrl->namespaces_rwsem); } int nvme_reset_ctrl(struct nvme_ctrl *ctrl) @@ -391,11 +400,9 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, switch (new_state) { case NVME_CTRL_LIVE: switch (old_state) { - case NVME_CTRL_CONNECTING: - nvme_stop_failfast_work(ctrl); - fallthrough; case NVME_CTRL_NEW: case NVME_CTRL_RESETTING: + case NVME_CTRL_CONNECTING: changed = true; fallthrough; default: @@ -4482,7 +4489,6 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev, int ret; ctrl->state = NVME_CTRL_NEW; - clear_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags); spin_lock_init(&ctrl->lock); mutex_init(&ctrl->scan_lock); INIT_LIST_HEAD(&ctrl->namespaces); diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c index 6404cbf41c96..d706fb5c3b19 100644 --- a/drivers/nvme/host/fabrics.c +++ b/drivers/nvme/host/fabrics.c @@ -547,9 +547,11 @@ static struct nvmf_transport_ops *nvmf_lookup_transport( blk_status_t nvmf_fail_nonready_command(struct nvme_ctrl *ctrl, struct request *rq) { + struct nvme_ns *ns = rq->rq_disk->private_data; + if (ctrl->state != NVME_CTRL_DELETING_NOIO && ctrl->state != NVME_CTRL_DEAD && - !test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags) && + !test_bit(NVME_NS_FAILFAST_EXPIRED, &ns->flags) && !blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH)) return BLK_STS_RESOURCE; diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 0e08ca6e0264..2738f08b2a07 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -155,9 +155,8 @@ static bool nvme_path_is_disabled(struct nvme_ns *ns) ns->ctrl->state != NVME_CTRL_DELETING) return true; if (test_bit(NVME_NS_ANA_PENDING, &ns->flags) || - test_bit(NVME_NS_REMOVING, &ns->flags)) - return true; - if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags)) + test_bit(NVME_NS_REMOVING, &ns->flags) || + test_bit(NVME_NS_FAILFAST_EXPIRED, &ns->flags)) return true; return false; } @@ -281,7 +280,7 @@ static bool nvme_available_path(struct nvme_ns_head *head) struct nvme_ns *ns; list_for_each_entry_rcu(ns, &head->list, siblings) { - if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags)) + if (test_bit(NVME_NS_FAILFAST_EXPIRED, &ns->flags)) continue; switch (ns->ctrl->state) { case NVME_CTRL_LIVE: @@ -490,8 +489,10 @@ static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc, ns->ana_state = desc->state; clear_bit(NVME_NS_ANA_PENDING, &ns->flags); - if (nvme_state_is_live(ns->ana_state)) + if (nvme_state_is_live(ns->ana_state)) { + clear_bit(NVME_NS_FAILFAST_EXPIRED, &ns->flags); nvme_mpath_set_live(ns); + } } static int nvme_update_ana_state(struct nvme_ctrl *ctrl, diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 37be7d16ab15..3163aa9fcf6d 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -338,8 +338,6 @@ struct nvme_ctrl { u16 icdoff; u16 maxcmd; int nr_reconnects; - unsigned long flags; -#define NVME_CTRL_FAILFAST_EXPIRED 0 struct nvmf_ctrl_options *opts; struct page *discard_page; @@ -451,6 +449,7 @@ struct nvme_ns { #define NVME_NS_REMOVING 0 #define NVME_NS_DEAD 1 #define NVME_NS_ANA_PENDING 2 +#define NVME_NS_FAILFAST_EXPIRED 3 struct nvme_fault_inject fault_inject; -- 2.16.4