Commit 5bbecdbc authored by James Smart's avatar James Smart Committed by Christoph Hellwig

nvme_fc: Support ctrl_loss_tmo

Sync with Sagi's recent addition of ctrl_loss_tmo in the core fabrics
layer.

Remove local connect limits and connect_attempts variable.
Use fabrics new nr_connects variable and use of nvmf_should_reconnect()
Refactor duplicate reconnect failure code.

Addresses review comment by Sagi on controller reset support:
http://lists.infradead.org/pipermail/linux-nvme/2017-April/009261.htmlSigned-off-by: default avatarJames Smart <james.smart@broadcom.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 0ce872bf
...@@ -45,8 +45,6 @@ enum nvme_fc_queue_flags { ...@@ -45,8 +45,6 @@ enum nvme_fc_queue_flags {
#define NVMEFC_QUEUE_DELAY 3 /* ms units */ #define NVMEFC_QUEUE_DELAY 3 /* ms units */
#define NVME_FC_MAX_CONNECT_ATTEMPTS 1
struct nvme_fc_queue { struct nvme_fc_queue {
struct nvme_fc_ctrl *ctrl; struct nvme_fc_ctrl *ctrl;
struct device *dev; struct device *dev;
...@@ -165,7 +163,6 @@ struct nvme_fc_ctrl { ...@@ -165,7 +163,6 @@ struct nvme_fc_ctrl {
struct work_struct delete_work; struct work_struct delete_work;
struct work_struct reset_work; struct work_struct reset_work;
struct delayed_work connect_work; struct delayed_work connect_work;
int connect_attempts;
struct kref ref; struct kref ref;
u32 flags; u32 flags;
...@@ -2305,7 +2302,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) ...@@ -2305,7 +2302,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
int ret; int ret;
bool changed; bool changed;
ctrl->connect_attempts++; ++ctrl->ctrl.opts->nr_reconnects;
/* /*
* Create the admin queue * Create the admin queue
...@@ -2402,7 +2399,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) ...@@ -2402,7 +2399,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
WARN_ON_ONCE(!changed); WARN_ON_ONCE(!changed);
ctrl->connect_attempts = 0; ctrl->ctrl.opts->nr_reconnects = 0;
kref_get(&ctrl->ctrl.kref); kref_get(&ctrl->ctrl.kref);
...@@ -2545,16 +2542,22 @@ nvme_fc_delete_ctrl_work(struct work_struct *work) ...@@ -2545,16 +2542,22 @@ nvme_fc_delete_ctrl_work(struct work_struct *work)
nvme_put_ctrl(&ctrl->ctrl); nvme_put_ctrl(&ctrl->ctrl);
} }
static int static bool
__nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl) __nvme_fc_schedule_delete_work(struct nvme_fc_ctrl *ctrl)
{ {
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING)) if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING))
return -EBUSY; return true;
if (!queue_work(nvme_fc_wq, &ctrl->delete_work)) if (!queue_work(nvme_fc_wq, &ctrl->delete_work))
return -EBUSY; return true;
return 0; return false;
}
static int
__nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl)
{
return __nvme_fc_schedule_delete_work(ctrl) ? -EBUSY : 0;
} }
/* /*
...@@ -2579,6 +2582,35 @@ nvme_fc_del_nvme_ctrl(struct nvme_ctrl *nctrl) ...@@ -2579,6 +2582,35 @@ nvme_fc_del_nvme_ctrl(struct nvme_ctrl *nctrl)
return ret; return ret;
} }
static void
nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
{
/* If we are resetting/deleting then do nothing */
if (ctrl->ctrl.state != NVME_CTRL_RECONNECTING) {
WARN_ON_ONCE(ctrl->ctrl.state == NVME_CTRL_NEW ||
ctrl->ctrl.state == NVME_CTRL_LIVE);
return;
}
dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n",
ctrl->cnum, status);
if (nvmf_should_reconnect(&ctrl->ctrl)) {
dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: Reconnect attempt in %d seconds.\n",
ctrl->cnum, ctrl->ctrl.opts->reconnect_delay);
queue_delayed_work(nvme_fc_wq, &ctrl->connect_work,
ctrl->ctrl.opts->reconnect_delay * HZ);
} else {
dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: Max reconnect attempts (%d) "
"reached. Removing controller\n",
ctrl->cnum, ctrl->ctrl.opts->nr_reconnects);
WARN_ON(__nvme_fc_schedule_delete_work(ctrl));
}
}
static void static void
nvme_fc_reset_ctrl_work(struct work_struct *work) nvme_fc_reset_ctrl_work(struct work_struct *work)
{ {
...@@ -2590,34 +2622,9 @@ nvme_fc_reset_ctrl_work(struct work_struct *work) ...@@ -2590,34 +2622,9 @@ nvme_fc_reset_ctrl_work(struct work_struct *work)
nvme_fc_delete_association(ctrl); nvme_fc_delete_association(ctrl);
ret = nvme_fc_create_association(ctrl); ret = nvme_fc_create_association(ctrl);
if (ret) { if (ret)
dev_warn(ctrl->ctrl.device, nvme_fc_reconnect_or_delete(ctrl, ret);
"NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n", else
ctrl->cnum, ret);
if (ctrl->connect_attempts >= NVME_FC_MAX_CONNECT_ATTEMPTS) {
dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: Max reconnect attempts (%d) "
"reached. Removing controller\n",
ctrl->cnum, ctrl->connect_attempts);
if (!nvme_change_ctrl_state(&ctrl->ctrl,
NVME_CTRL_DELETING)) {
dev_err(ctrl->ctrl.device,
"NVME-FC{%d}: failed to change state "
"to DELETING\n", ctrl->cnum);
return;
}
WARN_ON(!queue_work(nvme_fc_wq, &ctrl->delete_work));
return;
}
dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: Reconnect attempt in %d seconds.\n",
ctrl->cnum, ctrl->ctrl.opts->reconnect_delay);
queue_delayed_work(nvme_fc_wq, &ctrl->connect_work,
ctrl->ctrl.opts->reconnect_delay * HZ);
} else
dev_info(ctrl->ctrl.device, dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: controller reset complete\n", ctrl->cnum); "NVME-FC{%d}: controller reset complete\n", ctrl->cnum);
} }
...@@ -2670,34 +2677,9 @@ nvme_fc_connect_ctrl_work(struct work_struct *work) ...@@ -2670,34 +2677,9 @@ nvme_fc_connect_ctrl_work(struct work_struct *work)
struct nvme_fc_ctrl, connect_work); struct nvme_fc_ctrl, connect_work);
ret = nvme_fc_create_association(ctrl); ret = nvme_fc_create_association(ctrl);
if (ret) { if (ret)
dev_warn(ctrl->ctrl.device, nvme_fc_reconnect_or_delete(ctrl, ret);
"NVME-FC{%d}: Reconnect attempt failed (%d)\n", else
ctrl->cnum, ret);
if (ctrl->connect_attempts >= NVME_FC_MAX_CONNECT_ATTEMPTS) {
dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: Max reconnect attempts (%d) "
"reached. Removing controller\n",
ctrl->cnum, ctrl->connect_attempts);
if (!nvme_change_ctrl_state(&ctrl->ctrl,
NVME_CTRL_DELETING)) {
dev_err(ctrl->ctrl.device,
"NVME-FC{%d}: failed to change state "
"to DELETING\n", ctrl->cnum);
return;
}
WARN_ON(!queue_work(nvme_fc_wq, &ctrl->delete_work));
return;
}
dev_warn(ctrl->ctrl.device,
"NVME-FC{%d}: Reconnect attempt in %d seconds.\n",
ctrl->cnum, ctrl->ctrl.opts->reconnect_delay);
queue_delayed_work(nvme_fc_wq, &ctrl->connect_work,
ctrl->ctrl.opts->reconnect_delay * HZ);
} else
dev_info(ctrl->ctrl.device, dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: controller reconnect complete\n", "NVME-FC{%d}: controller reconnect complete\n",
ctrl->cnum); ctrl->cnum);
...@@ -2969,7 +2951,7 @@ nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts) ...@@ -2969,7 +2951,7 @@ nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts)
static struct nvmf_transport_ops nvme_fc_transport = { static struct nvmf_transport_ops nvme_fc_transport = {
.name = "fc", .name = "fc",
.required_opts = NVMF_OPT_TRADDR | NVMF_OPT_HOST_TRADDR, .required_opts = NVMF_OPT_TRADDR | NVMF_OPT_HOST_TRADDR,
.allowed_opts = NVMF_OPT_RECONNECT_DELAY, .allowed_opts = NVMF_OPT_RECONNECT_DELAY | NVMF_OPT_CTRL_LOSS_TMO,
.create_ctrl = nvme_fc_create_ctrl, .create_ctrl = nvme_fc_create_ctrl,
}; };
......
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