Commit 6d3c7fb1 authored by Keith Busch's avatar Keith Busch

nvme: use ctrl state accessor

The ctrl->state value is updated in another thread using WRITE_ONCE, so
ensure all the readers use the appropriate accessor.
Reviewed-by: default avatarSagi Grimberg <sagi@grmberg.me>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarChaitanya Kulkarni <kch@nvidia.com>
Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
parent 47c5dd66
...@@ -797,6 +797,7 @@ static int apple_nvme_init_request(struct blk_mq_tag_set *set, ...@@ -797,6 +797,7 @@ static int apple_nvme_init_request(struct blk_mq_tag_set *set,
static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown) static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown)
{ {
enum nvme_ctrl_state state = nvme_ctrl_state(&anv->ctrl);
u32 csts = readl(anv->mmio_nvme + NVME_REG_CSTS); u32 csts = readl(anv->mmio_nvme + NVME_REG_CSTS);
bool dead = false, freeze = false; bool dead = false, freeze = false;
unsigned long flags; unsigned long flags;
...@@ -808,8 +809,8 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown) ...@@ -808,8 +809,8 @@ static void apple_nvme_disable(struct apple_nvme *anv, bool shutdown)
if (csts & NVME_CSTS_CFS) if (csts & NVME_CSTS_CFS)
dead = true; dead = true;
if (anv->ctrl.state == NVME_CTRL_LIVE || if (state == NVME_CTRL_LIVE ||
anv->ctrl.state == NVME_CTRL_RESETTING) { state == NVME_CTRL_RESETTING) {
freeze = true; freeze = true;
nvme_start_freeze(&anv->ctrl); nvme_start_freeze(&anv->ctrl);
} }
...@@ -881,7 +882,7 @@ static enum blk_eh_timer_return apple_nvme_timeout(struct request *req) ...@@ -881,7 +882,7 @@ static enum blk_eh_timer_return apple_nvme_timeout(struct request *req)
unsigned long flags; unsigned long flags;
u32 csts = readl(anv->mmio_nvme + NVME_REG_CSTS); u32 csts = readl(anv->mmio_nvme + NVME_REG_CSTS);
if (anv->ctrl.state != NVME_CTRL_LIVE) { if (nvme_ctrl_state(&anv->ctrl) != NVME_CTRL_LIVE) {
/* /*
* From rdma.c: * From rdma.c:
* If we are resetting, connecting or deleting we should * If we are resetting, connecting or deleting we should
...@@ -985,10 +986,10 @@ static void apple_nvme_reset_work(struct work_struct *work) ...@@ -985,10 +986,10 @@ static void apple_nvme_reset_work(struct work_struct *work)
u32 boot_status, aqa; u32 boot_status, aqa;
struct apple_nvme *anv = struct apple_nvme *anv =
container_of(work, struct apple_nvme, ctrl.reset_work); container_of(work, struct apple_nvme, ctrl.reset_work);
enum nvme_ctrl_state state = nvme_ctrl_state(&anv->ctrl);
if (anv->ctrl.state != NVME_CTRL_RESETTING) { if (state != NVME_CTRL_RESETTING) {
dev_warn(anv->dev, "ctrl state %d is not RESETTING\n", dev_warn(anv->dev, "ctrl state %d is not RESETTING\n", state);
anv->ctrl.state);
ret = -ENODEV; ret = -ENODEV;
goto out; goto out;
} }
......
...@@ -897,7 +897,7 @@ static void nvme_ctrl_auth_work(struct work_struct *work) ...@@ -897,7 +897,7 @@ static void nvme_ctrl_auth_work(struct work_struct *work)
* If the ctrl is no connected, bail as reconnect will handle * If the ctrl is no connected, bail as reconnect will handle
* authentication. * authentication.
*/ */
if (ctrl->state != NVME_CTRL_LIVE) if (nvme_ctrl_state(ctrl) != NVME_CTRL_LIVE)
return; return;
/* Authenticate admin queue first */ /* Authenticate admin queue first */
......
...@@ -721,7 +721,7 @@ blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl, ...@@ -721,7 +721,7 @@ blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl,
EXPORT_SYMBOL_GPL(nvme_fail_nonready_command); EXPORT_SYMBOL_GPL(nvme_fail_nonready_command);
bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
bool queue_live) bool queue_live, enum nvme_ctrl_state state)
{ {
struct nvme_request *req = nvme_req(rq); struct nvme_request *req = nvme_req(rq);
...@@ -742,7 +742,7 @@ bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, ...@@ -742,7 +742,7 @@ bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
* command, which is require to set the queue live in the * command, which is require to set the queue live in the
* appropinquate states. * appropinquate states.
*/ */
switch (nvme_ctrl_state(ctrl)) { switch (state) {
case NVME_CTRL_CONNECTING: case NVME_CTRL_CONNECTING:
if (blk_rq_is_passthrough(rq) && nvme_is_fabrics(req->cmd) && if (blk_rq_is_passthrough(rq) && nvme_is_fabrics(req->cmd) &&
(req->cmd->fabrics.fctype == nvme_fabrics_type_connect || (req->cmd->fabrics.fctype == nvme_fabrics_type_connect ||
......
...@@ -185,9 +185,11 @@ static inline bool ...@@ -185,9 +185,11 @@ static inline bool
nvmf_ctlr_matches_baseopts(struct nvme_ctrl *ctrl, nvmf_ctlr_matches_baseopts(struct nvme_ctrl *ctrl,
struct nvmf_ctrl_options *opts) struct nvmf_ctrl_options *opts)
{ {
if (ctrl->state == NVME_CTRL_DELETING || enum nvme_ctrl_state state = nvme_ctrl_state(ctrl);
ctrl->state == NVME_CTRL_DELETING_NOIO ||
ctrl->state == NVME_CTRL_DEAD || if (state == NVME_CTRL_DELETING ||
state == NVME_CTRL_DELETING_NOIO ||
state == NVME_CTRL_DEAD ||
strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) || strcmp(opts->subsysnqn, ctrl->opts->subsysnqn) ||
strcmp(opts->host->nqn, ctrl->opts->host->nqn) || strcmp(opts->host->nqn, ctrl->opts->host->nqn) ||
!uuid_equal(&opts->host->id, &ctrl->opts->host->id)) !uuid_equal(&opts->host->id, &ctrl->opts->host->id))
......
...@@ -156,7 +156,7 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl) ...@@ -156,7 +156,7 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
if (!ns->head->disk) if (!ns->head->disk)
continue; continue;
kblockd_schedule_work(&ns->head->requeue_work); kblockd_schedule_work(&ns->head->requeue_work);
if (ctrl->state == NVME_CTRL_LIVE) if (nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE)
disk_uevent(ns->head->disk, KOBJ_CHANGE); disk_uevent(ns->head->disk, KOBJ_CHANGE);
} }
up_read(&ctrl->namespaces_rwsem); up_read(&ctrl->namespaces_rwsem);
...@@ -223,13 +223,14 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns) ...@@ -223,13 +223,14 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns)
static bool nvme_path_is_disabled(struct nvme_ns *ns) static bool nvme_path_is_disabled(struct nvme_ns *ns)
{ {
enum nvme_ctrl_state state = nvme_ctrl_state(ns->ctrl);
/* /*
* We don't treat NVME_CTRL_DELETING as a disabled path as I/O should * We don't treat NVME_CTRL_DELETING as a disabled path as I/O should
* still be able to complete assuming that the controller is connected. * still be able to complete assuming that the controller is connected.
* Otherwise it will fail immediately and return to the requeue list. * Otherwise it will fail immediately and return to the requeue list.
*/ */
if (ns->ctrl->state != NVME_CTRL_LIVE && if (state != NVME_CTRL_LIVE && state != NVME_CTRL_DELETING)
ns->ctrl->state != NVME_CTRL_DELETING)
return true; return true;
if (test_bit(NVME_NS_ANA_PENDING, &ns->flags) || if (test_bit(NVME_NS_ANA_PENDING, &ns->flags) ||
!test_bit(NVME_NS_READY, &ns->flags)) !test_bit(NVME_NS_READY, &ns->flags))
...@@ -331,7 +332,7 @@ static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head, ...@@ -331,7 +332,7 @@ static struct nvme_ns *nvme_round_robin_path(struct nvme_ns_head *head,
static inline bool nvme_path_is_optimized(struct nvme_ns *ns) static inline bool nvme_path_is_optimized(struct nvme_ns *ns)
{ {
return ns->ctrl->state == NVME_CTRL_LIVE && return nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE &&
ns->ana_state == NVME_ANA_OPTIMIZED; ns->ana_state == NVME_ANA_OPTIMIZED;
} }
...@@ -358,7 +359,7 @@ static bool nvme_available_path(struct nvme_ns_head *head) ...@@ -358,7 +359,7 @@ static bool nvme_available_path(struct nvme_ns_head *head)
list_for_each_entry_rcu(ns, &head->list, siblings) { list_for_each_entry_rcu(ns, &head->list, siblings) {
if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags)) if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags))
continue; continue;
switch (ns->ctrl->state) { switch (nvme_ctrl_state(ns->ctrl)) {
case NVME_CTRL_LIVE: case NVME_CTRL_LIVE:
case NVME_CTRL_RESETTING: case NVME_CTRL_RESETTING:
case NVME_CTRL_CONNECTING: case NVME_CTRL_CONNECTING:
...@@ -667,7 +668,7 @@ static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc, ...@@ -667,7 +668,7 @@ static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc,
* controller is ready. * controller is ready.
*/ */
if (nvme_state_is_live(ns->ana_state) && if (nvme_state_is_live(ns->ana_state) &&
ns->ctrl->state == NVME_CTRL_LIVE) nvme_ctrl_state(ns->ctrl) == NVME_CTRL_LIVE)
nvme_mpath_set_live(ns); nvme_mpath_set_live(ns);
} }
...@@ -748,7 +749,7 @@ static void nvme_ana_work(struct work_struct *work) ...@@ -748,7 +749,7 @@ static void nvme_ana_work(struct work_struct *work)
{ {
struct nvme_ctrl *ctrl = container_of(work, struct nvme_ctrl, ana_work); struct nvme_ctrl *ctrl = container_of(work, struct nvme_ctrl, ana_work);
if (ctrl->state != NVME_CTRL_LIVE) if (nvme_ctrl_state(ctrl) != NVME_CTRL_LIVE)
return; return;
nvme_read_ana_log(ctrl); nvme_read_ana_log(ctrl);
......
...@@ -805,17 +805,18 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req); ...@@ -805,17 +805,18 @@ blk_status_t nvme_setup_cmd(struct nvme_ns *ns, struct request *req);
blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl, blk_status_t nvme_fail_nonready_command(struct nvme_ctrl *ctrl,
struct request *req); struct request *req);
bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, bool __nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
bool queue_live); bool queue_live, enum nvme_ctrl_state state);
static inline bool nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq, static inline bool nvme_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
bool queue_live) bool queue_live)
{ {
if (likely(ctrl->state == NVME_CTRL_LIVE)) enum nvme_ctrl_state state = nvme_ctrl_state(ctrl);
if (likely(state == NVME_CTRL_LIVE))
return true; return true;
if (ctrl->ops->flags & NVME_F_FABRICS && if (ctrl->ops->flags & NVME_F_FABRICS && state == NVME_CTRL_DELETING)
ctrl->state == NVME_CTRL_DELETING)
return queue_live; return queue_live;
return __nvme_check_ready(ctrl, rq, queue_live); return __nvme_check_ready(ctrl, rq, queue_live, state);
} }
/* /*
......
...@@ -311,6 +311,7 @@ static ssize_t nvme_sysfs_show_state(struct device *dev, ...@@ -311,6 +311,7 @@ static ssize_t nvme_sysfs_show_state(struct device *dev,
char *buf) char *buf)
{ {
struct nvme_ctrl *ctrl = dev_get_drvdata(dev); struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
unsigned state = (unsigned)nvme_ctrl_state(ctrl);
static const char *const state_name[] = { static const char *const state_name[] = {
[NVME_CTRL_NEW] = "new", [NVME_CTRL_NEW] = "new",
[NVME_CTRL_LIVE] = "live", [NVME_CTRL_LIVE] = "live",
...@@ -321,9 +322,8 @@ static ssize_t nvme_sysfs_show_state(struct device *dev, ...@@ -321,9 +322,8 @@ static ssize_t nvme_sysfs_show_state(struct device *dev,
[NVME_CTRL_DEAD] = "dead", [NVME_CTRL_DEAD] = "dead",
}; };
if ((unsigned)ctrl->state < ARRAY_SIZE(state_name) && if (state < ARRAY_SIZE(state_name) && state_name[state])
state_name[ctrl->state]) return sysfs_emit(buf, "%s\n", state_name[state]);
return sysfs_emit(buf, "%s\n", state_name[ctrl->state]);
return sysfs_emit(buf, "unknown state\n"); return sysfs_emit(buf, "unknown state\n");
} }
......
...@@ -400,7 +400,7 @@ static void nvme_loop_shutdown_ctrl(struct nvme_loop_ctrl *ctrl) ...@@ -400,7 +400,7 @@ static void nvme_loop_shutdown_ctrl(struct nvme_loop_ctrl *ctrl)
} }
nvme_quiesce_admin_queue(&ctrl->ctrl); nvme_quiesce_admin_queue(&ctrl->ctrl);
if (ctrl->ctrl.state == NVME_CTRL_LIVE) if (nvme_ctrl_state(&ctrl->ctrl) == NVME_CTRL_LIVE)
nvme_disable_ctrl(&ctrl->ctrl, true); nvme_disable_ctrl(&ctrl->ctrl, true);
nvme_cancel_admin_tagset(&ctrl->ctrl); nvme_cancel_admin_tagset(&ctrl->ctrl);
...@@ -434,8 +434,10 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work) ...@@ -434,8 +434,10 @@ static void nvme_loop_reset_ctrl_work(struct work_struct *work)
nvme_loop_shutdown_ctrl(ctrl); nvme_loop_shutdown_ctrl(ctrl);
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) { if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) {
if (ctrl->ctrl.state != NVME_CTRL_DELETING && enum nvme_ctrl_state state = nvme_ctrl_state(&ctrl->ctrl);
ctrl->ctrl.state != NVME_CTRL_DELETING_NOIO)
if (state != NVME_CTRL_DELETING &&
state != NVME_CTRL_DELETING_NOIO)
/* state change failure for non-deleted ctrl? */ /* state change failure for non-deleted ctrl? */
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment