| From da8c0a9979bdb7ebb128287479396f444d69353f Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 21 Jan 2021 11:32:37 +0800 |
| Subject: nvme-rdma: add clean action for failed reconnection |
| |
| From: Chao Leng <lengchao@huawei.com> |
| |
| [ Upstream commit 958dc1d32c80566f58d18f05ef1f05bd32d172c1 ] |
| |
| A crash happens when inject failed reconnection. |
| If reconnect failed after start io queues, the queues will be unquiesced |
| and new requests continue to be delivered. Reconnection error handling |
| process directly free queues without cancel suspend requests. The |
| suppend request will time out, and then crash due to use the queue |
| after free. |
| |
| Add sync queues and cancel suppend requests for reconnection error |
| handling. |
| |
| Signed-off-by: Chao Leng <lengchao@huawei.com> |
| Signed-off-by: Christoph Hellwig <hch@lst.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/nvme/host/rdma.c | 18 ++++++++++++++++-- |
| 1 file changed, 16 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c |
| index b7ce4f221d99..746392eade45 100644 |
| --- a/drivers/nvme/host/rdma.c |
| +++ b/drivers/nvme/host/rdma.c |
| @@ -919,12 +919,16 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl, |
| |
| error = nvme_init_identify(&ctrl->ctrl); |
| if (error) |
| - goto out_stop_queue; |
| + goto out_quiesce_queue; |
| |
| return 0; |
| |
| +out_quiesce_queue: |
| + blk_mq_quiesce_queue(ctrl->ctrl.admin_q); |
| + blk_sync_queue(ctrl->ctrl.admin_q); |
| out_stop_queue: |
| nvme_rdma_stop_queue(&ctrl->queues[0]); |
| + nvme_cancel_admin_tagset(&ctrl->ctrl); |
| out_cleanup_queue: |
| if (new) |
| blk_cleanup_queue(ctrl->ctrl.admin_q); |
| @@ -1001,8 +1005,10 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new) |
| |
| out_wait_freeze_timed_out: |
| nvme_stop_queues(&ctrl->ctrl); |
| + nvme_sync_io_queues(&ctrl->ctrl); |
| nvme_rdma_stop_io_queues(ctrl); |
| out_cleanup_connect_q: |
| + nvme_cancel_tagset(&ctrl->ctrl); |
| if (new) |
| blk_cleanup_queue(ctrl->ctrl.connect_q); |
| out_free_tag_set: |
| @@ -1144,10 +1150,18 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new) |
| return 0; |
| |
| destroy_io: |
| - if (ctrl->ctrl.queue_count > 1) |
| + if (ctrl->ctrl.queue_count > 1) { |
| + nvme_stop_queues(&ctrl->ctrl); |
| + nvme_sync_io_queues(&ctrl->ctrl); |
| + nvme_rdma_stop_io_queues(ctrl); |
| + nvme_cancel_tagset(&ctrl->ctrl); |
| nvme_rdma_destroy_io_queues(ctrl, new); |
| + } |
| destroy_admin: |
| + blk_mq_quiesce_queue(ctrl->ctrl.admin_q); |
| + blk_sync_queue(ctrl->ctrl.admin_q); |
| nvme_rdma_stop_queue(&ctrl->queues[0]); |
| + nvme_cancel_admin_tagset(&ctrl->ctrl); |
| nvme_rdma_destroy_admin_queue(ctrl, new); |
| return ret; |
| } |
| -- |
| 2.30.1 |
| |