After the controller is recovered, it isn't necessary to wait for completion of all in-flight IO. More importantly, it is easy to trigger deadlock if there is new IO timeout triggered. Cc: Tejun Heo <tj@xxxxxxxxxx> Cc: Jianchao Wang <jianchao.w.wang@xxxxxxxxxx> Cc: Kent Overstreet <kent.overstreet@xxxxxxxxx> Cc: linux-block@xxxxxxxxxxxxxxx Cc: Christoph Hellwig <hch@xxxxxx> Cc: linux-nvme@xxxxxxxxxxxxxxxxxxx Cc: Keith Busch <keith.busch@xxxxxxxxx> Signed-off-by: Ming Lei <ming.lei@xxxxxxxxxx> --- drivers/nvme/host/core.c | 12 ++++++++---- drivers/nvme/host/nvme.h | 2 +- drivers/nvme/host/pci.c | 3 +-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index dd8ec1dd9219..cf6a2267d44e 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1203,7 +1203,7 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects) if (effects & NVME_CMD_EFFECTS_LBCC) nvme_update_formats(ctrl); if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) - nvme_unfreeze(ctrl); + nvme_unfreeze(ctrl, true); if (effects & NVME_CMD_EFFECTS_CCC) nvme_init_identify(ctrl); if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC)) @@ -3602,13 +3602,17 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl) } EXPORT_SYMBOL_GPL(nvme_kill_queues); -void nvme_unfreeze(struct nvme_ctrl *ctrl) +void nvme_unfreeze(struct nvme_ctrl *ctrl, bool check_io_drained) { struct nvme_ns *ns; down_read(&ctrl->namespaces_rwsem); - list_for_each_entry(ns, &ctrl->namespaces, list) - blk_mq_unfreeze_queue(ns->queue); + list_for_each_entry(ns, &ctrl->namespaces, list) { + if (check_io_drained) + blk_mq_unfreeze_queue(ns->queue); + else + blk_mq_unfreeze_queue_no_drain_io(ns->queue); + } up_read(&ctrl->namespaces_rwsem); } EXPORT_SYMBOL_GPL(nvme_unfreeze); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index bb4a2003c097..fd56270637d1 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -432,7 +432,7 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status, void nvme_stop_queues(struct nvme_ctrl *ctrl); void nvme_start_queues(struct nvme_ctrl *ctrl); void nvme_kill_queues(struct nvme_ctrl *ctrl); -void nvme_unfreeze(struct nvme_ctrl *ctrl); +void nvme_unfreeze(struct nvme_ctrl *ctrl, bool check_io_drained); void nvme_wait_freeze(struct nvme_ctrl *ctrl); void nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout); void nvme_start_freeze(struct nvme_ctrl *ctrl); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index d668682f91df..1c26a2e92063 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2328,11 +2328,10 @@ static void nvme_reset_work(struct work_struct *work) new_state = NVME_CTRL_ADMIN_ONLY; } else { nvme_start_queues(&dev->ctrl); - nvme_wait_freeze(&dev->ctrl); /* hit this only when allocate tagset fails */ if (nvme_dev_add(dev)) new_state = NVME_CTRL_ADMIN_ONLY; - nvme_unfreeze(&dev->ctrl); + nvme_unfreeze(&dev->ctrl, false); } /* -- 2.9.5