| From f1ebeb222a0847e1fb239175dbedd3fcebab7afb Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 21 Jan 2021 11:32:38 +0800 |
| Subject: nvme-tcp: add clean action for failed reconnection |
| |
| From: Chao Leng <lengchao@huawei.com> |
| |
| [ Upstream commit 70a99574a79f1cd4dc7ad56ea37be40844bfb97b ] |
| |
| 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/tcp.c | 18 ++++++++++++++++-- |
| 1 file changed, 16 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c |
| index 881d28eb15e9..30d24a5a5b82 100644 |
| --- a/drivers/nvme/host/tcp.c |
| +++ b/drivers/nvme/host/tcp.c |
| @@ -1815,8 +1815,10 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new) |
| |
| out_wait_freeze_timed_out: |
| nvme_stop_queues(ctrl); |
| + nvme_sync_io_queues(ctrl); |
| nvme_tcp_stop_io_queues(ctrl); |
| out_cleanup_connect_q: |
| + nvme_cancel_tagset(ctrl); |
| if (new) |
| blk_cleanup_queue(ctrl->connect_q); |
| out_free_tag_set: |
| @@ -1878,12 +1880,16 @@ static int nvme_tcp_configure_admin_queue(struct nvme_ctrl *ctrl, bool new) |
| |
| error = nvme_init_identify(ctrl); |
| if (error) |
| - goto out_stop_queue; |
| + goto out_quiesce_queue; |
| |
| return 0; |
| |
| +out_quiesce_queue: |
| + blk_mq_quiesce_queue(ctrl->admin_q); |
| + blk_sync_queue(ctrl->admin_q); |
| out_stop_queue: |
| nvme_tcp_stop_queue(ctrl, 0); |
| + nvme_cancel_admin_tagset(ctrl); |
| out_cleanup_queue: |
| if (new) |
| blk_cleanup_queue(ctrl->admin_q); |
| @@ -2003,10 +2009,18 @@ static int nvme_tcp_setup_ctrl(struct nvme_ctrl *ctrl, bool new) |
| return 0; |
| |
| destroy_io: |
| - if (ctrl->queue_count > 1) |
| + if (ctrl->queue_count > 1) { |
| + nvme_stop_queues(ctrl); |
| + nvme_sync_io_queues(ctrl); |
| + nvme_tcp_stop_io_queues(ctrl); |
| + nvme_cancel_tagset(ctrl); |
| nvme_tcp_destroy_io_queues(ctrl, new); |
| + } |
| destroy_admin: |
| + blk_mq_quiesce_queue(ctrl->admin_q); |
| + blk_sync_queue(ctrl->admin_q); |
| nvme_tcp_stop_queue(ctrl, 0); |
| + nvme_cancel_admin_tagset(ctrl); |
| nvme_tcp_destroy_admin_queue(ctrl, new); |
| return ret; |
| } |
| -- |
| 2.30.1 |
| |