提交 12057ba1 编写于 作者: S Sagi Grimberg 提交者: Yang Yingliang

nvme-rdma: fix timeout handler

mainline inclusion
from mainline-v5.9-rc4
commit 0475a8dc
category: bugfix
bugzilla: NA
CVE: NA
Link: https://gitee.com/openeuler/kernel/issues/I1WGZE

-------------------------------------------------

When a request times out in a LIVE state, we simply trigger error
recovery and let the error recovery handle the request cancellation,
however when a request times out in a non LIVE state, we make sure to
complete it immediately as it might block controller setup or teardown
and prevent forward progress.

However tearing down the entire set of I/O and admin queues causes
freeze/unfreeze imbalance (q->mq_freeze_depth) because and is really
an overkill to what we actually need, which is to just fence controller
teardown that may be running, stop the queue, and cancel the request if
it is not already completed.

Now that we have the controller teardown_lock, we can safely serialize
request cancellation. This addresses a hang caused by calling extra
queue freeze on controller namespaces, causing unfreeze to not complete
correctly.
Reviewed-by: NChristoph Hellwig <hch@lst.de>
Reviewed-by: NJames Smart <james.smart@broadcom.com>
Signed-off-by: NSagi Grimberg <sagi@grimberg.me>
Reviewed-by: NChao Leng <lengchao@huawei.com>
Reviewed-by: NJike Cheng <chengjike.cheng@huawei.com>
Conflicts:
  drivers/nvme/host/rdma.c
[lrz: adjust context]
Signed-off-by: NRuozhu Li <liruozhu@huawei.com>
Signed-off-by: NLijie <lijie34@huawei.com>
Reviewed-by: NTao Hou <houtao1@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 86825596
...@@ -1045,6 +1045,7 @@ static void nvme_rdma_error_recovery(struct nvme_rdma_ctrl *ctrl) ...@@ -1045,6 +1045,7 @@ static void nvme_rdma_error_recovery(struct nvme_rdma_ctrl *ctrl)
if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING)) if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING))
return; return;
dev_warn(ctrl->ctrl.device, "starting error recovery\n");
queue_work(nvme_wq, &ctrl->err_work); queue_work(nvme_wq, &ctrl->err_work);
} }
...@@ -1660,6 +1661,22 @@ static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id, ...@@ -1660,6 +1661,22 @@ static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id,
return 0; return 0;
} }
static void nvme_rdma_complete_timed_out(struct request *rq)
{
struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
struct nvme_rdma_queue *queue = req->queue;
struct nvme_rdma_ctrl *ctrl = queue->ctrl;
/* fence other contexts that may complete the command */
mutex_lock(&ctrl->teardown_lock);
nvme_rdma_stop_queue(queue);
if (!blk_mq_request_completed(rq)) {
nvme_req(rq)->status = NVME_SC_HOST_ABORTED_CMD;
blk_mq_complete_request(rq);
}
mutex_unlock(&ctrl->teardown_lock);
}
static enum blk_eh_timer_return static enum blk_eh_timer_return
nvme_rdma_timeout(struct request *rq, bool reserved) nvme_rdma_timeout(struct request *rq, bool reserved)
{ {
...@@ -1672,19 +1689,27 @@ nvme_rdma_timeout(struct request *rq, bool reserved) ...@@ -1672,19 +1689,27 @@ nvme_rdma_timeout(struct request *rq, bool reserved)
if (ctrl->ctrl.state != NVME_CTRL_LIVE) { if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
/* /*
* Teardown immediately if controller times out while starting * If we are resetting, connecting or deleting we should
* or we are already started error recovery. all outstanding * complete immediately because we may block controller
* requests are completed on shutdown, so we return BLK_EH_DONE. * teardown or setup sequence
* - ctrl disable/shutdown fabrics requests
* - connect requests
* - initialization admin requests
* - I/O requests that entered after unquiescing and
* the controller stopped responding
*
* All other requests should be cancelled by the error
* recovery work, so it's fine that we fail it here.
*/ */
flush_work(&ctrl->err_work); nvme_rdma_complete_timed_out(rq);
nvme_rdma_teardown_io_queues(ctrl, false);
nvme_rdma_teardown_admin_queue(ctrl, false);
return BLK_EH_DONE; return BLK_EH_DONE;
} }
dev_warn(ctrl->ctrl.device, "starting error recovery\n"); /*
* LIVE state should trigger the normal error recovery which will
* handle completing this request.
*/
nvme_rdma_error_recovery(ctrl); nvme_rdma_error_recovery(ctrl);
return BLK_EH_RESET_TIMER; return BLK_EH_RESET_TIMER;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册