|
@@ -45,8 +45,6 @@ enum nvme_fc_queue_flags {
|
|
|
|
|
|
#define NVMEFC_QUEUE_DELAY 3 /* ms units */
|
|
|
|
|
|
-#define NVME_FC_MAX_CONNECT_ATTEMPTS 1
|
|
|
-
|
|
|
struct nvme_fc_queue {
|
|
|
struct nvme_fc_ctrl *ctrl;
|
|
|
struct device *dev;
|
|
@@ -165,7 +163,6 @@ struct nvme_fc_ctrl {
|
|
|
struct work_struct delete_work;
|
|
|
struct work_struct reset_work;
|
|
|
struct delayed_work connect_work;
|
|
|
- int connect_attempts;
|
|
|
|
|
|
struct kref ref;
|
|
|
u32 flags;
|
|
@@ -2305,7 +2302,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
|
|
|
int ret;
|
|
|
bool changed;
|
|
|
|
|
|
- ctrl->connect_attempts++;
|
|
|
+ ++ctrl->ctrl.opts->nr_reconnects;
|
|
|
|
|
|
/*
|
|
|
* Create the admin queue
|
|
@@ -2402,7 +2399,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
|
|
|
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
|
|
|
WARN_ON_ONCE(!changed);
|
|
|
|
|
|
- ctrl->connect_attempts = 0;
|
|
|
+ ctrl->ctrl.opts->nr_reconnects = 0;
|
|
|
|
|
|
kref_get(&ctrl->ctrl.kref);
|
|
|
|
|
@@ -2545,16 +2542,22 @@ nvme_fc_delete_ctrl_work(struct work_struct *work)
|
|
|
nvme_put_ctrl(&ctrl->ctrl);
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-__nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl)
|
|
|
+static bool
|
|
|
+__nvme_fc_schedule_delete_work(struct nvme_fc_ctrl *ctrl)
|
|
|
{
|
|
|
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING))
|
|
|
- return -EBUSY;
|
|
|
+ return true;
|
|
|
|
|
|
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)
|
|
|
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
|
|
|
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);
|
|
|
|
|
|
ret = nvme_fc_create_association(ctrl);
|
|
|
- if (ret) {
|
|
|
- dev_warn(ctrl->ctrl.device,
|
|
|
- "NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n",
|
|
|
- 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
|
|
|
+ if (ret)
|
|
|
+ nvme_fc_reconnect_or_delete(ctrl, ret);
|
|
|
+ else
|
|
|
dev_info(ctrl->ctrl.device,
|
|
|
"NVME-FC{%d}: controller reset complete\n", ctrl->cnum);
|
|
|
}
|
|
@@ -2670,34 +2677,9 @@ nvme_fc_connect_ctrl_work(struct work_struct *work)
|
|
|
struct nvme_fc_ctrl, connect_work);
|
|
|
|
|
|
ret = nvme_fc_create_association(ctrl);
|
|
|
- if (ret) {
|
|
|
- dev_warn(ctrl->ctrl.device,
|
|
|
- "NVME-FC{%d}: Reconnect attempt failed (%d)\n",
|
|
|
- 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
|
|
|
+ if (ret)
|
|
|
+ nvme_fc_reconnect_or_delete(ctrl, ret);
|
|
|
+ else
|
|
|
dev_info(ctrl->ctrl.device,
|
|
|
"NVME-FC{%d}: controller reconnect complete\n",
|
|
|
ctrl->cnum);
|
|
@@ -2969,7 +2951,7 @@ nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts)
|
|
|
static struct nvmf_transport_ops nvme_fc_transport = {
|
|
|
.name = "fc",
|
|
|
.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,
|
|
|
};
|
|
|
|