[PATCH RFC v2 09/14] nvme: Coordinate CDQ backing mem and CDQ FD

Joel Granados <[email protected]>
Newsgroups org.kernel.feeds.b4-sent,org.infradead.lists.linux-nvme,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
The user space file descriptor fails if the memory backing the
Controller Data Queue (CDQ) is not "valid". This can happen as part of
the controller tear-down procedure.

Test the valid_mem variable when reading the from the file descriptor.
Set on CDQ creation and unset when the CDQ is being deleted on the host
side.

Signed-off-by: Joel Granados <[email protected]>
---
 drivers/nvme/host/cdq.c | 20 ++++++++++++++++++--
 drivers/nvme/host/cdq.h |  3 +++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/host/cdq.c b/drivers/nvme/host/cdq.c
index 0f01b58a9c3145faae83a81627fa5a93cfc03cf4..7fe08afa0d80db5f3d60993aba05624b5c59b309 100644
--- a/drivers/nvme/host/cdq.c
+++ b/drivers/nvme/host/cdq.c
@@ -184,6 +184,9 @@ static ssize_t nvme_cdq_fops_read(struct file *filep, char __user *buf,
 	if (nbytes > (cdq->size_nbyte))
 		return -EINVAL;
 
+	if (!READ_ONCE(cdq->valid_mem))
+		return -EINVAL;
+
 	/* CDQ traversal not implemented yet. */
 	return -EOPNOTSUPP;
 }
@@ -207,7 +210,16 @@ static const struct file_operations cdq_fops = {
 	.release	= nvme_cdq_fops_release,
 };
 
-__maybe_unused
+/* Should only handle cdq struct and ctrl kref */
+void nvme_free_cdq(struct kref *ref)
+{
+	struct cdq_nvme_queue *cdq = container_of(ref, struct cdq_nvme_queue, ref);
+
+	/* Drop the ctrl kref held since creation */
+	nvme_put_ctrl(cdq->ctrl);
+	kfree(cdq);
+}
+
 static int nvme_create_cdqfd(struct cdq_nvme_queue *cdq, int *cdq_fdno)
 {
 	int fdno;
@@ -276,8 +288,9 @@ static void nvme_delete_cdq_host(struct cdq_nvme_queue *cdq)
 	if (xa_erase(&ctrl->cdqs, cdq->id) != cdq)
 		return;
 
-	nvme_release_cdq_backing(cdq);
+	WRITE_ONCE(cdq->valid_mem, false);
 
+	nvme_release_cdq_backing(cdq);
 	nvme_cdq_put(cdq);
 }
 
@@ -342,11 +355,14 @@ int nvme_create_cdq(struct nvme_ctrl *ctrl, const u32 entry_nr, const u16 mc_id)
 	}
 
 	kref_init(&cdq->ref);
+	nvme_get_ctrl(cdq->ctrl);
 
 	ret = nvme_submit_create_cdq_cmd(cdq);
 	if (ret)
 		goto del_cdqmem;
 
+	WRITE_ONCE(cdq->valid_mem, true);
+
 	ret = xa_insert(&cdq->ctrl->cdqs, cdq->id, cdq, GFP_KERNEL);
 	if (ret)
 		goto del_cmd;
diff --git a/drivers/nvme/host/cdq.h b/drivers/nvme/host/cdq.h
index 773f93817d498784450eb0c8c9ab00a95f0657dc..aa9469af0c7ef08b9f8ebf93e468c7f892aee4b1 100644
--- a/drivers/nvme/host/cdq.h
+++ b/drivers/nvme/host/cdq.h
@@ -42,6 +42,9 @@ struct cdq_nvme_queue {
 	dma_addr_t prp_lists_dma[MAX_NR_CDQ_PRPS];
 	unsigned int nr_prp_lists;
 
+	/* True if mem for chunks and prps is valid */
+	bool valid_mem;
+
 	/* Manage refs for read FD and controller xarray */
 	struct kref ref;
 };

-- 
2.50.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.