diff options
author | James Smart <jsmart2021@gmail.com> | 2017-05-15 20:10:16 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2017-05-22 14:55:29 -0400 |
commit | 5bbecdbc8e7ffaaf47ac1f02014bf3bedda3fd11 (patch) | |
tree | 25db7d8e340e52ff0af524b3cd59c1066ee183af | |
parent | 0ce872bf8b5c4d425a41940a523ff1b8daa0b275 (diff) |
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.html
Signed-off-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r-- | drivers/nvme/host/fc.c | 116 |
1 files changed, 49 insertions, 67 deletions
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index c3ab1043efbd..a0f05d5e966c 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c | |||
@@ -45,8 +45,6 @@ enum nvme_fc_queue_flags { | |||
45 | 45 | ||
46 | #define NVMEFC_QUEUE_DELAY 3 /* ms units */ | 46 | #define NVMEFC_QUEUE_DELAY 3 /* ms units */ |
47 | 47 | ||
48 | #define NVME_FC_MAX_CONNECT_ATTEMPTS 1 | ||
49 | |||
50 | struct nvme_fc_queue { | 48 | struct nvme_fc_queue { |
51 | struct nvme_fc_ctrl *ctrl; | 49 | struct nvme_fc_ctrl *ctrl; |
52 | struct device *dev; | 50 | struct device *dev; |
@@ -165,7 +163,6 @@ struct nvme_fc_ctrl { | |||
165 | struct work_struct delete_work; | 163 | struct work_struct delete_work; |
166 | struct work_struct reset_work; | 164 | struct work_struct reset_work; |
167 | struct delayed_work connect_work; | 165 | struct delayed_work connect_work; |
168 | int connect_attempts; | ||
169 | 166 | ||
170 | struct kref ref; | 167 | struct kref ref; |
171 | u32 flags; | 168 | u32 flags; |
@@ -2305,7 +2302,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) | |||
2305 | int ret; | 2302 | int ret; |
2306 | bool changed; | 2303 | bool changed; |
2307 | 2304 | ||
2308 | ctrl->connect_attempts++; | 2305 | ++ctrl->ctrl.opts->nr_reconnects; |
2309 | 2306 | ||
2310 | /* | 2307 | /* |
2311 | * Create the admin queue | 2308 | * Create the admin queue |
@@ -2402,7 +2399,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) | |||
2402 | changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); | 2399 | changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); |
2403 | WARN_ON_ONCE(!changed); | 2400 | WARN_ON_ONCE(!changed); |
2404 | 2401 | ||
2405 | ctrl->connect_attempts = 0; | 2402 | ctrl->ctrl.opts->nr_reconnects = 0; |
2406 | 2403 | ||
2407 | kref_get(&ctrl->ctrl.kref); | 2404 | kref_get(&ctrl->ctrl.kref); |
2408 | 2405 | ||
@@ -2545,16 +2542,22 @@ nvme_fc_delete_ctrl_work(struct work_struct *work) | |||
2545 | nvme_put_ctrl(&ctrl->ctrl); | 2542 | nvme_put_ctrl(&ctrl->ctrl); |
2546 | } | 2543 | } |
2547 | 2544 | ||
2548 | static int | 2545 | static bool |
2549 | __nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl) | 2546 | __nvme_fc_schedule_delete_work(struct nvme_fc_ctrl *ctrl) |
2550 | { | 2547 | { |
2551 | if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING)) | 2548 | if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING)) |
2552 | return -EBUSY; | 2549 | return true; |
2553 | 2550 | ||
2554 | if (!queue_work(nvme_fc_wq, &ctrl->delete_work)) | 2551 | if (!queue_work(nvme_fc_wq, &ctrl->delete_work)) |
2555 | return -EBUSY; | 2552 | return true; |
2556 | 2553 | ||
2557 | return 0; | 2554 | return false; |
2555 | } | ||
2556 | |||
2557 | static int | ||
2558 | __nvme_fc_del_ctrl(struct nvme_fc_ctrl *ctrl) | ||
2559 | { | ||
2560 | return __nvme_fc_schedule_delete_work(ctrl) ? -EBUSY : 0; | ||
2558 | } | 2561 | } |
2559 | 2562 | ||
2560 | /* | 2563 | /* |
@@ -2580,6 +2583,35 @@ nvme_fc_del_nvme_ctrl(struct nvme_ctrl *nctrl) | |||
2580 | } | 2583 | } |
2581 | 2584 | ||
2582 | static void | 2585 | static void |
2586 | nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status) | ||
2587 | { | ||
2588 | /* If we are resetting/deleting then do nothing */ | ||
2589 | if (ctrl->ctrl.state != NVME_CTRL_RECONNECTING) { | ||
2590 | WARN_ON_ONCE(ctrl->ctrl.state == NVME_CTRL_NEW || | ||
2591 | ctrl->ctrl.state == NVME_CTRL_LIVE); | ||
2592 | return; | ||
2593 | } | ||
2594 | |||
2595 | dev_warn(ctrl->ctrl.device, | ||
2596 | "NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n", | ||
2597 | ctrl->cnum, status); | ||
2598 | |||
2599 | if (nvmf_should_reconnect(&ctrl->ctrl)) { | ||
2600 | dev_info(ctrl->ctrl.device, | ||
2601 | "NVME-FC{%d}: Reconnect attempt in %d seconds.\n", | ||
2602 | ctrl->cnum, ctrl->ctrl.opts->reconnect_delay); | ||
2603 | queue_delayed_work(nvme_fc_wq, &ctrl->connect_work, | ||
2604 | ctrl->ctrl.opts->reconnect_delay * HZ); | ||
2605 | } else { | ||
2606 | dev_info(ctrl->ctrl.device, | ||
2607 | "NVME-FC{%d}: Max reconnect attempts (%d) " | ||
2608 | "reached. Removing controller\n", | ||
2609 | ctrl->cnum, ctrl->ctrl.opts->nr_reconnects); | ||
2610 | WARN_ON(__nvme_fc_schedule_delete_work(ctrl)); | ||
2611 | } | ||
2612 | } | ||
2613 | |||
2614 | static void | ||
2583 | nvme_fc_reset_ctrl_work(struct work_struct *work) | 2615 | nvme_fc_reset_ctrl_work(struct work_struct *work) |
2584 | { | 2616 | { |
2585 | struct nvme_fc_ctrl *ctrl = | 2617 | struct nvme_fc_ctrl *ctrl = |
@@ -2590,34 +2622,9 @@ nvme_fc_reset_ctrl_work(struct work_struct *work) | |||
2590 | nvme_fc_delete_association(ctrl); | 2622 | nvme_fc_delete_association(ctrl); |
2591 | 2623 | ||
2592 | ret = nvme_fc_create_association(ctrl); | 2624 | ret = nvme_fc_create_association(ctrl); |
2593 | if (ret) { | 2625 | if (ret) |
2594 | dev_warn(ctrl->ctrl.device, | 2626 | nvme_fc_reconnect_or_delete(ctrl, ret); |
2595 | "NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n", | 2627 | else |
2596 | ctrl->cnum, ret); | ||
2597 | if (ctrl->connect_attempts >= NVME_FC_MAX_CONNECT_ATTEMPTS) { | ||
2598 | dev_warn(ctrl->ctrl.device, | ||
2599 | "NVME-FC{%d}: Max reconnect attempts (%d) " | ||
2600 | "reached. Removing controller\n", | ||
2601 | ctrl->cnum, ctrl->connect_attempts); | ||
2602 | |||
2603 | if (!nvme_change_ctrl_state(&ctrl->ctrl, | ||
2604 | NVME_CTRL_DELETING)) { | ||
2605 | dev_err(ctrl->ctrl.device, | ||
2606 | "NVME-FC{%d}: failed to change state " | ||
2607 | "to DELETING\n", ctrl->cnum); | ||
2608 | return; | ||
2609 | } | ||
2610 | |||
2611 | WARN_ON(!queue_work(nvme_fc_wq, &ctrl->delete_work)); | ||
2612 | return; | ||
2613 | } | ||
2614 | |||
2615 | dev_warn(ctrl->ctrl.device, | ||
2616 | "NVME-FC{%d}: Reconnect attempt in %d seconds.\n", | ||
2617 | ctrl->cnum, ctrl->ctrl.opts->reconnect_delay); | ||
2618 | queue_delayed_work(nvme_fc_wq, &ctrl->connect_work, | ||
2619 | ctrl->ctrl.opts->reconnect_delay * HZ); | ||
2620 | } else | ||
2621 | dev_info(ctrl->ctrl.device, | 2628 | dev_info(ctrl->ctrl.device, |
2622 | "NVME-FC{%d}: controller reset complete\n", ctrl->cnum); | 2629 | "NVME-FC{%d}: controller reset complete\n", ctrl->cnum); |
2623 | } | 2630 | } |
@@ -2670,34 +2677,9 @@ nvme_fc_connect_ctrl_work(struct work_struct *work) | |||
2670 | struct nvme_fc_ctrl, connect_work); | 2677 | struct nvme_fc_ctrl, connect_work); |
2671 | 2678 | ||
2672 | ret = nvme_fc_create_association(ctrl); | 2679 | ret = nvme_fc_create_association(ctrl); |
2673 | if (ret) { | 2680 | if (ret) |
2674 | dev_warn(ctrl->ctrl.device, | 2681 | nvme_fc_reconnect_or_delete(ctrl, ret); |
2675 | "NVME-FC{%d}: Reconnect attempt failed (%d)\n", | 2682 | else |
2676 | ctrl->cnum, ret); | ||
2677 | if (ctrl->connect_attempts >= NVME_FC_MAX_CONNECT_ATTEMPTS) { | ||
2678 | dev_warn(ctrl->ctrl.device, | ||
2679 | "NVME-FC{%d}: Max reconnect attempts (%d) " | ||
2680 | "reached. Removing controller\n", | ||
2681 | ctrl->cnum, ctrl->connect_attempts); | ||
2682 | |||
2683 | if (!nvme_change_ctrl_state(&ctrl->ctrl, | ||
2684 | NVME_CTRL_DELETING)) { | ||
2685 | dev_err(ctrl->ctrl.device, | ||
2686 | "NVME-FC{%d}: failed to change state " | ||
2687 | "to DELETING\n", ctrl->cnum); | ||
2688 | return; | ||
2689 | } | ||
2690 | |||
2691 | WARN_ON(!queue_work(nvme_fc_wq, &ctrl->delete_work)); | ||
2692 | return; | ||
2693 | } | ||
2694 | |||
2695 | dev_warn(ctrl->ctrl.device, | ||
2696 | "NVME-FC{%d}: Reconnect attempt in %d seconds.\n", | ||
2697 | ctrl->cnum, ctrl->ctrl.opts->reconnect_delay); | ||
2698 | queue_delayed_work(nvme_fc_wq, &ctrl->connect_work, | ||
2699 | ctrl->ctrl.opts->reconnect_delay * HZ); | ||
2700 | } else | ||
2701 | dev_info(ctrl->ctrl.device, | 2683 | dev_info(ctrl->ctrl.device, |
2702 | "NVME-FC{%d}: controller reconnect complete\n", | 2684 | "NVME-FC{%d}: controller reconnect complete\n", |
2703 | ctrl->cnum); | 2685 | ctrl->cnum); |
@@ -2969,7 +2951,7 @@ nvme_fc_create_ctrl(struct device *dev, struct nvmf_ctrl_options *opts) | |||
2969 | static struct nvmf_transport_ops nvme_fc_transport = { | 2951 | static struct nvmf_transport_ops nvme_fc_transport = { |
2970 | .name = "fc", | 2952 | .name = "fc", |
2971 | .required_opts = NVMF_OPT_TRADDR | NVMF_OPT_HOST_TRADDR, | 2953 | .required_opts = NVMF_OPT_TRADDR | NVMF_OPT_HOST_TRADDR, |
2972 | .allowed_opts = NVMF_OPT_RECONNECT_DELAY, | 2954 | .allowed_opts = NVMF_OPT_RECONNECT_DELAY | NVMF_OPT_CTRL_LOSS_TMO, |
2973 | .create_ctrl = nvme_fc_create_ctrl, | 2955 | .create_ctrl = nvme_fc_create_ctrl, |
2974 | }; | 2956 | }; |
2975 | 2957 | ||