Skip to content

Commit c655278

Browse files
igawopsiff
authored andcommitted
nvme-fc: do not ignore connectivity loss during connecting
[ Upstream commit ee59e38 ] When a connectivity loss occurs while nvme_fc_create_assocation is being executed, it's possible that the ctrl ends up stuck in the LIVE state: 1) nvme nvme10: NVME-FC{10}: create association : ... 2) nvme nvme10: NVME-FC{10}: controller connectivity lost. Awaiting Reconnect nvme nvme10: queue_size 128 > ctrl maxcmd 32, reducing to maxcmd 3) nvme nvme10: Could not set queue count (880) nvme nvme10: Failed to configure AEN (cfg 900) 4) nvme nvme10: NVME-FC{10}: controller connect complete 5) nvme nvme10: failed nvme_keep_alive_end_io error=4 A connection attempt starts 1) and the ctrl is in state CONNECTING. Shortly after the LLDD driver detects a connection lost event and calls nvme_fc_ctrl_connectivity_loss 2). Because we are still in CONNECTING state, this event is ignored. nvme_fc_create_association continues to run in parallel and tries to communicate with the controller and these commands will fail. Though these errors are filtered out, e.g in 3) setting the I/O queues numbers fails which leads to an early exit in nvme_fc_create_io_queues. Because the number of IO queues is 0 at this point, there is nothing left in nvme_fc_create_association which could detected the connection drop. Thus the ctrl enters LIVE state 4). Eventually the keep alive handler times out 5) but because nothing is being done, the ctrl stays in LIVE state. There is already the ASSOC_FAILED flag to track connectivity loss event but this bit is set too late in the recovery code path. Move this into the connectivity loss event handler and synchronize it with the state change. This ensures that the ASSOC_FAILED flag is seen by nvme_fc_create_io_queues and it does not enter the LIVE state after a connectivity loss event. If the connectivity loss event happens after we entered the LIVE state the normal error recovery path is executed. Signed-off-by: Daniel Wagner <wagi@kernel.org> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit fa5bfdd)
1 parent 2d7e9c1 commit c655278

1 file changed

Lines changed: 18 additions & 5 deletions

File tree

  • drivers/nvme/host

drivers/nvme/host/fc.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -782,11 +782,19 @@ nvme_fc_abort_lsops(struct nvme_fc_rport *rport)
782782
static void
783783
nvme_fc_ctrl_connectivity_loss(struct nvme_fc_ctrl *ctrl)
784784
{
785+
enum nvme_ctrl_state state;
786+
unsigned long flags;
787+
785788
dev_info(ctrl->ctrl.device,
786789
"NVME-FC{%d}: controller connectivity lost. Awaiting "
787790
"Reconnect", ctrl->cnum);
788791

789-
switch (nvme_ctrl_state(&ctrl->ctrl)) {
792+
spin_lock_irqsave(&ctrl->lock, flags);
793+
set_bit(ASSOC_FAILED, &ctrl->flags);
794+
state = nvme_ctrl_state(&ctrl->ctrl);
795+
spin_unlock_irqrestore(&ctrl->lock, flags);
796+
797+
switch (state) {
790798
case NVME_CTRL_NEW:
791799
case NVME_CTRL_LIVE:
792800
/*
@@ -2546,7 +2554,6 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
25462554
*/
25472555
if (state == NVME_CTRL_CONNECTING) {
25482556
__nvme_fc_abort_outstanding_ios(ctrl, true);
2549-
set_bit(ASSOC_FAILED, &ctrl->flags);
25502557
dev_warn(ctrl->ctrl.device,
25512558
"NVME-FC{%d}: transport error during (re)connect\n",
25522559
ctrl->cnum);
@@ -3168,12 +3175,18 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
31683175
else
31693176
ret = nvme_fc_recreate_io_queues(ctrl);
31703177
}
3171-
if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags))
3172-
ret = -EIO;
31733178
if (ret)
31743179
goto out_term_aen_ops;
31753180

3176-
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
3181+
spin_lock_irqsave(&ctrl->lock, flags);
3182+
if (!test_bit(ASSOC_FAILED, &ctrl->flags))
3183+
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
3184+
else
3185+
ret = -EIO;
3186+
spin_unlock_irqrestore(&ctrl->lock, flags);
3187+
3188+
if (ret)
3189+
goto out_term_aen_ops;
31773190

31783191
ctrl->ctrl.nr_reconnects = 0;
31793192

0 commit comments

Comments
 (0)