Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4875622 authored by Keith Busch's avatar Keith Busch Committed by Jens Axboe
Browse files

nvme/pci: Don't free queues on error



The nvme_remove function tears down all allocated resources in the correct
order, so no need to free queues on error during initialization. This
fixes possible use-after-free errors when queues are still associated
with a blk-mq hctx.

Reported-by: default avatarScott Bauer <scott.bauer@intel.com>
Tested-by: default avatarScott Bauer <scott.bauer@intel.com>
Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
Reviewed-by: default avatarSagi Grimberg <sagi@grimbeg.me>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarJens Axboe <axboe@fb.com>
parent 959401aa
Loading
Loading
Loading
Loading
+4 −14
Original line number Original line Diff line number Diff line
@@ -1242,20 +1242,16 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)


	result = nvme_enable_ctrl(&dev->ctrl, cap);
	result = nvme_enable_ctrl(&dev->ctrl, cap);
	if (result)
	if (result)
		goto free_nvmeq;
		return result;


	nvmeq->cq_vector = 0;
	nvmeq->cq_vector = 0;
	result = queue_request_irq(nvmeq);
	result = queue_request_irq(nvmeq);
	if (result) {
	if (result) {
		nvmeq->cq_vector = -1;
		nvmeq->cq_vector = -1;
		goto free_nvmeq;
		return result;
	}
	}


	return result;
	return result;

 free_nvmeq:
	nvme_free_queues(dev, 0);
	return result;
}
}


static bool nvme_should_reset(struct nvme_dev *dev, u32 csts)
static bool nvme_should_reset(struct nvme_dev *dev, u32 csts)
@@ -1317,11 +1313,9 @@ static int nvme_create_io_queues(struct nvme_dev *dev)
	max = min(dev->max_qid, dev->queue_count - 1);
	max = min(dev->max_qid, dev->queue_count - 1);
	for (i = dev->online_queues; i <= max; i++) {
	for (i = dev->online_queues; i <= max; i++) {
		ret = nvme_create_queue(dev->queues[i], i);
		ret = nvme_create_queue(dev->queues[i], i);
		if (ret) {
		if (ret)
			nvme_free_queues(dev, i);
			break;
			break;
	}
	}
	}


	/*
	/*
	 * Ignore failing Create SQ/CQ commands, we can continue with less
	 * Ignore failing Create SQ/CQ commands, we can continue with less
@@ -1460,13 +1454,9 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
	result = queue_request_irq(adminq);
	result = queue_request_irq(adminq);
	if (result) {
	if (result) {
		adminq->cq_vector = -1;
		adminq->cq_vector = -1;
		goto free_queues;
		return result;
	}
	}
	return nvme_create_io_queues(dev);
	return nvme_create_io_queues(dev);

 free_queues:
	nvme_free_queues(dev, 1);
	return result;
}
}


static void nvme_del_queue_end(struct request *req, int error)
static void nvme_del_queue_end(struct request *req, int error)