aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2015-06-08 12:08:13 -0400
committerJens Axboe <axboe@fb.com>2015-06-27 13:42:48 -0400
commit4af0e21caf8e676e57ea27d7cce3426e473e498c (patch)
tree3fd31d7943eec6ec08cb915513ef71d9c67aa607
parentd2c3ac7e7e39ec6d37e4114ae7444948561e59af (diff)
NVMe: Fix device cleanup on initialization failure
Don't release block queue and tagging resoureces if the driver never got them in the first place. This can happen if the controller fails to become ready, if memory wasn't available to allocate a tagset or admin queue, or if the resources were released as part of error recovery. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--drivers/block/nvme-core.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index e5112714188f..a45700312caf 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -193,6 +193,13 @@ static int nvme_admin_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
193 return 0; 193 return 0;
194} 194}
195 195
196static void nvme_admin_exit_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
197{
198 struct nvme_queue *nvmeq = hctx->driver_data;
199
200 nvmeq->tags = NULL;
201}
202
196static int nvme_admin_init_request(void *data, struct request *req, 203static int nvme_admin_init_request(void *data, struct request *req,
197 unsigned int hctx_idx, unsigned int rq_idx, 204 unsigned int hctx_idx, unsigned int rq_idx,
198 unsigned int numa_node) 205 unsigned int numa_node)
@@ -1606,6 +1613,7 @@ static struct blk_mq_ops nvme_mq_admin_ops = {
1606 .queue_rq = nvme_queue_rq, 1613 .queue_rq = nvme_queue_rq,
1607 .map_queue = blk_mq_map_queue, 1614 .map_queue = blk_mq_map_queue,
1608 .init_hctx = nvme_admin_init_hctx, 1615 .init_hctx = nvme_admin_init_hctx,
1616 .exit_hctx = nvme_admin_exit_hctx,
1609 .init_request = nvme_admin_init_request, 1617 .init_request = nvme_admin_init_request,
1610 .timeout = nvme_timeout, 1618 .timeout = nvme_timeout,
1611}; 1619};
@@ -1648,6 +1656,7 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev)
1648 } 1656 }
1649 if (!blk_get_queue(dev->admin_q)) { 1657 if (!blk_get_queue(dev->admin_q)) {
1650 nvme_dev_remove_admin(dev); 1658 nvme_dev_remove_admin(dev);
1659 dev->admin_q = NULL;
1651 return -ENODEV; 1660 return -ENODEV;
1652 } 1661 }
1653 } else 1662 } else
@@ -2734,8 +2743,10 @@ static void nvme_free_dev(struct kref *kref)
2734 put_device(dev->device); 2743 put_device(dev->device);
2735 nvme_free_namespaces(dev); 2744 nvme_free_namespaces(dev);
2736 nvme_release_instance(dev); 2745 nvme_release_instance(dev);
2737 blk_mq_free_tag_set(&dev->tagset); 2746 if (dev->tagset.tags)
2738 blk_put_queue(dev->admin_q); 2747 blk_mq_free_tag_set(&dev->tagset);
2748 if (dev->admin_q)
2749 blk_put_queue(dev->admin_q);
2739 kfree(dev->queues); 2750 kfree(dev->queues);
2740 kfree(dev->entry); 2751 kfree(dev->entry);
2741 kfree(dev); 2752 kfree(dev);
@@ -2866,6 +2877,9 @@ static int nvme_dev_start(struct nvme_dev *dev)
2866 2877
2867 free_tags: 2878 free_tags:
2868 nvme_dev_remove_admin(dev); 2879 nvme_dev_remove_admin(dev);
2880 blk_put_queue(dev->admin_q);
2881 dev->admin_q = NULL;
2882 dev->queues[0]->tags = NULL;
2869 disable: 2883 disable:
2870 nvme_disable_queue(dev, 0); 2884 nvme_disable_queue(dev, 0);
2871 nvme_dev_list_remove(dev); 2885 nvme_dev_list_remove(dev);