* [PATCH v2 0/2] NVMe PCI endpoint target fixes
@ 2025-03-06 8:55 Damien Le Moal
2025-03-06 8:55 ` [PATCH v2 1/2] nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created Damien Le Moal
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Damien Le Moal @ 2025-03-06 8:55 UTC (permalink / raw)
To: linux-nvme, Keith Busch, Christoph Hellwig, Sagi Grimberg
All,
A couple of fixes for the NVMe PCI endpoint target driver. The first
patch fixes an issue that sometimes causes crashes (hard to reproduce).
Changes from v1:
- Fix a screwup in patch 2: the error path in nvmet_pci_epf_create_cq()
was calling nvmet_pci_epf_remove_irq_vector() depending on
NVMET_PCI_EPF_Q_LIVE being set instead of NVMET_PCI_EPF_Q_IRQ_ENABLED
being set.
Damien Le Moal (2):
nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created
nvmet: pci-epf: Do not add an IRQ vector if not needed
drivers/nvme/target/pci-epf.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
--
2.48.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/2] nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created
2025-03-06 8:55 [PATCH v2 0/2] NVMe PCI endpoint target fixes Damien Le Moal
@ 2025-03-06 8:55 ` Damien Le Moal
2025-03-06 14:14 ` Christoph Hellwig
2025-03-06 8:55 ` [PATCH v2 2/2] nvmet: pci-epf: Do not add an IRQ vector if not needed Damien Le Moal
2025-03-10 17:15 ` [PATCH v2 0/2] NVMe PCI endpoint target fixes Keith Busch
2 siblings, 1 reply; 6+ messages in thread
From: Damien Le Moal @ 2025-03-06 8:55 UTC (permalink / raw)
To: linux-nvme, Keith Busch, Christoph Hellwig, Sagi Grimberg
The function nvmet_pci_epf_create_sq() use test_and_set_bit() to check
that a submission queue is not already live and if not, set the
NVMET_PCI_EPF_Q_LIVE queue flag to declare the sq live (ready to use).
However, this is done on entry to the function, before the submission
queue is actually fully initialized and ready to use. This creates a
race situation with the function nvmet_pci_epf_poll_sqs_work() which
looks at the NVMET_PCI_EPF_Q_LIVE queue flag to poll the submission
queue when it is live. This race can lead to invalid DMA transfers if
nvmet_pci_epf_poll_sqs_work() runs after the NVMET_PCI_EPF_Q_LIVE flag
is set but before setting the sq pci address and doorbell ofset.
Avoid this race by only testing the NVMET_PCI_EPF_Q_LIVE flag on entry
to nvmet_pci_epf_create_sq() and setting it after the submission queue
is fully setup before nvmet_pci_epf_create_sq() returns success.
Since the function nvmet_pci_epf_create_cq() also has the same racy flag
setting pattern, also make a similar change in that function.
Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver")
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
drivers/nvme/target/pci-epf.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index 565d2bd36dcd..d55ad334670c 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -1265,7 +1265,7 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
struct nvmet_pci_epf_queue *cq = &ctrl->cq[cqid];
u16 status;
- if (test_and_set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags))
+ if (test_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags))
return NVME_SC_QID_INVALID | NVME_STATUS_DNR;
if (!(flags & NVME_QUEUE_PHYS_CONTIG))
@@ -1300,6 +1300,8 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
if (status != NVME_SC_SUCCESS)
goto err;
+ set_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags);
+
dev_dbg(ctrl->dev, "CQ[%u]: %u entries of %zu B, IRQ vector %u\n",
cqid, qsize, cq->qes, cq->vector);
@@ -1307,7 +1309,6 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
err:
clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags);
- clear_bit(NVMET_PCI_EPF_Q_LIVE, &cq->flags);
return status;
}
@@ -1333,7 +1334,7 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl,
struct nvmet_pci_epf_queue *sq = &ctrl->sq[sqid];
u16 status;
- if (test_and_set_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags))
+ if (test_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags))
return NVME_SC_QID_INVALID | NVME_STATUS_DNR;
if (!(flags & NVME_QUEUE_PHYS_CONTIG))
@@ -1355,7 +1356,7 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl,
status = nvmet_sq_create(tctrl, &sq->nvme_sq, sqid, sq->depth);
if (status != NVME_SC_SUCCESS)
- goto out_clear_bit;
+ return status;
sq->iod_wq = alloc_workqueue("sq%d_wq", WQ_UNBOUND,
min_t(int, sq->depth, WQ_MAX_ACTIVE), sqid);
@@ -1365,6 +1366,8 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl,
goto out_destroy_sq;
}
+ set_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags);
+
dev_dbg(ctrl->dev, "SQ[%u]: %u entries of %zu B\n",
sqid, qsize, sq->qes);
@@ -1372,8 +1375,6 @@ static u16 nvmet_pci_epf_create_sq(struct nvmet_ctrl *tctrl,
out_destroy_sq:
nvmet_sq_destroy(&sq->nvme_sq);
-out_clear_bit:
- clear_bit(NVMET_PCI_EPF_Q_LIVE, &sq->flags);
return status;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] nvmet: pci-epf: Do not add an IRQ vector if not needed
2025-03-06 8:55 [PATCH v2 0/2] NVMe PCI endpoint target fixes Damien Le Moal
2025-03-06 8:55 ` [PATCH v2 1/2] nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created Damien Le Moal
@ 2025-03-06 8:55 ` Damien Le Moal
2025-03-06 14:14 ` Christoph Hellwig
2025-03-10 17:15 ` [PATCH v2 0/2] NVMe PCI endpoint target fixes Keith Busch
2 siblings, 1 reply; 6+ messages in thread
From: Damien Le Moal @ 2025-03-06 8:55 UTC (permalink / raw)
To: linux-nvme, Keith Busch, Christoph Hellwig, Sagi Grimberg
The function nvmet_pci_epf_create_cq() always unconditionally calls
nvmet_pci_epf_add_irq_vector() to add an IRQ vector for a completion
queue. But this is not correct if the host requested the creation of a
completion queue for polling, without an IRQ vector specified (i.e. the
flag NVME_CQ_IRQ_ENABLED is not set).
Fix this by calling nvmet_pci_epf_add_irq_vector() and setting the queue
flag NVMET_PCI_EPF_Q_IRQ_ENABLED for the cq only if NVME_CQ_IRQ_ENABLED
is set. While at it, also fix the error path to add the missing removal
of the added IRQ vector if nvmet_cq_create() fails.
Fixes: 0faa0fe6f90e ("nvmet: New NVMe PCI endpoint function target driver")
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
---
drivers/nvme/target/pci-epf.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index d55ad334670c..b1e31483f157 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -1271,9 +1271,6 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
if (!(flags & NVME_QUEUE_PHYS_CONTIG))
return NVME_SC_INVALID_QUEUE | NVME_STATUS_DNR;
- if (flags & NVME_CQ_IRQ_ENABLED)
- set_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags);
-
cq->pci_addr = pci_addr;
cq->qid = cqid;
cq->depth = qsize + 1;
@@ -1290,10 +1287,11 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
cq->qes = ctrl->io_cqes;
cq->pci_size = cq->qes * cq->depth;
- cq->iv = nvmet_pci_epf_add_irq_vector(ctrl, vector);
- if (!cq->iv) {
- status = NVME_SC_INTERNAL | NVME_STATUS_DNR;
- goto err;
+ if (flags & NVME_CQ_IRQ_ENABLED) {
+ cq->iv = nvmet_pci_epf_add_irq_vector(ctrl, vector);
+ if (!cq->iv)
+ return NVME_SC_INTERNAL | NVME_STATUS_DNR;
+ set_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags);
}
status = nvmet_cq_create(tctrl, &cq->nvme_cq, cqid, cq->depth);
@@ -1308,7 +1306,8 @@ static u16 nvmet_pci_epf_create_cq(struct nvmet_ctrl *tctrl,
return NVME_SC_SUCCESS;
err:
- clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags);
+ if (test_and_clear_bit(NVMET_PCI_EPF_Q_IRQ_ENABLED, &cq->flags))
+ nvmet_pci_epf_remove_irq_vector(ctrl, cq->vector);
return status;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created
2025-03-06 8:55 ` [PATCH v2 1/2] nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created Damien Le Moal
@ 2025-03-06 14:14 ` Christoph Hellwig
0 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2025-03-06 14:14 UTC (permalink / raw)
To: Damien Le Moal; +Cc: linux-nvme, Keith Busch, Christoph Hellwig, Sagi Grimberg
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] nvmet: pci-epf: Do not add an IRQ vector if not needed
2025-03-06 8:55 ` [PATCH v2 2/2] nvmet: pci-epf: Do not add an IRQ vector if not needed Damien Le Moal
@ 2025-03-06 14:14 ` Christoph Hellwig
0 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2025-03-06 14:14 UTC (permalink / raw)
To: Damien Le Moal; +Cc: linux-nvme, Keith Busch, Christoph Hellwig, Sagi Grimberg
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/2] NVMe PCI endpoint target fixes
2025-03-06 8:55 [PATCH v2 0/2] NVMe PCI endpoint target fixes Damien Le Moal
2025-03-06 8:55 ` [PATCH v2 1/2] nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created Damien Le Moal
2025-03-06 8:55 ` [PATCH v2 2/2] nvmet: pci-epf: Do not add an IRQ vector if not needed Damien Le Moal
@ 2025-03-10 17:15 ` Keith Busch
2 siblings, 0 replies; 6+ messages in thread
From: Keith Busch @ 2025-03-10 17:15 UTC (permalink / raw)
To: Damien Le Moal; +Cc: linux-nvme, Christoph Hellwig, Sagi Grimberg
On Thu, Mar 06, 2025 at 05:55:47PM +0900, Damien Le Moal wrote:
> A couple of fixes for the NVMe PCI endpoint target driver. The first
> patch fixes an issue that sometimes causes crashes (hard to reproduce).
THanks, applied to nvme-6.14.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-03-10 18:35 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-06 8:55 [PATCH v2 0/2] NVMe PCI endpoint target fixes Damien Le Moal
2025-03-06 8:55 ` [PATCH v2 1/2] nvmet: pci-epf: Set NVMET_PCI_EPF_Q_LIVE when a queue is fully created Damien Le Moal
2025-03-06 14:14 ` Christoph Hellwig
2025-03-06 8:55 ` [PATCH v2 2/2] nvmet: pci-epf: Do not add an IRQ vector if not needed Damien Le Moal
2025-03-06 14:14 ` Christoph Hellwig
2025-03-10 17:15 ` [PATCH v2 0/2] NVMe PCI endpoint target fixes Keith Busch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox