aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIsrael Rukshin <israelr@mellanox.com>2018-06-19 08:34:11 -0400
committerChristoph Hellwig <hch@lst.de>2018-06-20 08:20:51 -0400
commitc947657b15379505a9bba36a02005882b66abe57 (patch)
tree252bc9998774c6eb77d2e0dd31c850ec0d2db67d
parent94e42213cc1ae41c57819539c0130f8dfc69d718 (diff)
nvme-rdma: Fix command completion race at error recovery
The race is between completing the request at error recovery work and rdma completions. If we cancel the request before getting the good rdma completion we get a NULL deref of the request MR at nvme_rdma_process_nvme_rsp(). When Canceling the request we return its mr to the mr pool (set mr to NULL) and also unmap its data. Canceling the requests while the rdma queues are active is not safe. Because rdma queues are active and we get good rdma completions that can use the mr pointer which may be NULL. Completing the request too soon may lead also to performing DMA to/from user buffers which might have been already unmapped. The commit fixes the race by draining the QP before starting the abort commands mechanism. Signed-off-by: Israel Rukshin <israelr@mellanox.com> Reviewed-by: Max Gurtovoy <maxg@mellanox.com> Signed-off-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--drivers/nvme/host/rdma.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index f9affb71ac85..2815749f4dfb 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -728,7 +728,6 @@ out:
728static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl, 728static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl,
729 bool remove) 729 bool remove)
730{ 730{
731 nvme_rdma_stop_queue(&ctrl->queues[0]);
732 if (remove) { 731 if (remove) {
733 blk_cleanup_queue(ctrl->ctrl.admin_q); 732 blk_cleanup_queue(ctrl->ctrl.admin_q);
734 nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.admin_tagset); 733 nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.admin_tagset);
@@ -817,7 +816,6 @@ out_free_queue:
817static void nvme_rdma_destroy_io_queues(struct nvme_rdma_ctrl *ctrl, 816static void nvme_rdma_destroy_io_queues(struct nvme_rdma_ctrl *ctrl,
818 bool remove) 817 bool remove)
819{ 818{
820 nvme_rdma_stop_io_queues(ctrl);
821 if (remove) { 819 if (remove) {
822 blk_cleanup_queue(ctrl->ctrl.connect_q); 820 blk_cleanup_queue(ctrl->ctrl.connect_q);
823 nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.tagset); 821 nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.tagset);
@@ -947,6 +945,7 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
947 return; 945 return;
948 946
949destroy_admin: 947destroy_admin:
948 nvme_rdma_stop_queue(&ctrl->queues[0]);
950 nvme_rdma_destroy_admin_queue(ctrl, false); 949 nvme_rdma_destroy_admin_queue(ctrl, false);
951requeue: 950requeue:
952 dev_info(ctrl->ctrl.device, "Failed reconnect attempt %d\n", 951 dev_info(ctrl->ctrl.device, "Failed reconnect attempt %d\n",
@@ -963,12 +962,14 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
963 962
964 if (ctrl->ctrl.queue_count > 1) { 963 if (ctrl->ctrl.queue_count > 1) {
965 nvme_stop_queues(&ctrl->ctrl); 964 nvme_stop_queues(&ctrl->ctrl);
965 nvme_rdma_stop_io_queues(ctrl);
966 blk_mq_tagset_busy_iter(&ctrl->tag_set, 966 blk_mq_tagset_busy_iter(&ctrl->tag_set,
967 nvme_cancel_request, &ctrl->ctrl); 967 nvme_cancel_request, &ctrl->ctrl);
968 nvme_rdma_destroy_io_queues(ctrl, false); 968 nvme_rdma_destroy_io_queues(ctrl, false);
969 } 969 }
970 970
971 blk_mq_quiesce_queue(ctrl->ctrl.admin_q); 971 blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
972 nvme_rdma_stop_queue(&ctrl->queues[0]);
972 blk_mq_tagset_busy_iter(&ctrl->admin_tag_set, 973 blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
973 nvme_cancel_request, &ctrl->ctrl); 974 nvme_cancel_request, &ctrl->ctrl);
974 nvme_rdma_destroy_admin_queue(ctrl, false); 975 nvme_rdma_destroy_admin_queue(ctrl, false);
@@ -1734,6 +1735,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
1734{ 1735{
1735 if (ctrl->ctrl.queue_count > 1) { 1736 if (ctrl->ctrl.queue_count > 1) {
1736 nvme_stop_queues(&ctrl->ctrl); 1737 nvme_stop_queues(&ctrl->ctrl);
1738 nvme_rdma_stop_io_queues(ctrl);
1737 blk_mq_tagset_busy_iter(&ctrl->tag_set, 1739 blk_mq_tagset_busy_iter(&ctrl->tag_set,
1738 nvme_cancel_request, &ctrl->ctrl); 1740 nvme_cancel_request, &ctrl->ctrl);
1739 nvme_rdma_destroy_io_queues(ctrl, shutdown); 1741 nvme_rdma_destroy_io_queues(ctrl, shutdown);
@@ -1745,6 +1747,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
1745 nvme_disable_ctrl(&ctrl->ctrl, ctrl->ctrl.cap); 1747 nvme_disable_ctrl(&ctrl->ctrl, ctrl->ctrl.cap);
1746 1748
1747 blk_mq_quiesce_queue(ctrl->ctrl.admin_q); 1749 blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
1750 nvme_rdma_stop_queue(&ctrl->queues[0]);
1748 blk_mq_tagset_busy_iter(&ctrl->admin_tag_set, 1751 blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
1749 nvme_cancel_request, &ctrl->ctrl); 1752 nvme_cancel_request, &ctrl->ctrl);
1750 blk_mq_unquiesce_queue(ctrl->ctrl.admin_q); 1753 blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
@@ -2011,6 +2014,7 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
2011 return &ctrl->ctrl; 2014 return &ctrl->ctrl;
2012 2015
2013out_remove_admin_queue: 2016out_remove_admin_queue:
2017 nvme_rdma_stop_queue(&ctrl->queues[0]);
2014 nvme_rdma_destroy_admin_queue(ctrl, true); 2018 nvme_rdma_destroy_admin_queue(ctrl, true);
2015out_uninit_ctrl: 2019out_uninit_ctrl:
2016 nvme_uninit_ctrl(&ctrl->ctrl); 2020 nvme_uninit_ctrl(&ctrl->ctrl);