* [PATCH] nvme/host: Fix RCU list traversal to use SRCU primitive
@ 2024-11-04 12:24 Breno Leitao
2024-11-04 13:16 ` Christoph Hellwig
0 siblings, 1 reply; 3+ messages in thread
From: Breno Leitao @ 2024-11-04 12:24 UTC (permalink / raw)
To: Keith Busch, Jens Axboe, Christoph Hellwig, Sagi Grimberg
Cc: linux-nvme, linux-kernel, kernel-team, Breno Leitao
The code currently uses list_for_each_entry_rcu() while holding an SRCU
lock, triggering false positive warnings with CONFIG_PROVE_RCU=y
enabled:
drivers/nvme/host/core.c:3770 RCU-list traversed in non-reader section!!
While the list is properly protected by SRCU lock, the code uses the wrong
list traversal primitive. Replace list_for_each_entry_rcu() with
list_for_each_entry_srcu() to correctly indicate SRCU-based protection
and eliminate the false warning.
Signed-off-by: Breno Leitao <leitao@debian.org>
Fixes: be647e2c76b2 ("nvme: use srcu for iterating namespace list")
---
Something similar will need to be done for multipath. I will get it done
once I get some feedback about this patch first.
---
drivers/nvme/host/core.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 84cb859a911d09dbe71b2f1ac473ae687c4dc687..3583bae69ef74c6f1fe6d465531a9a09512a6f13 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3767,7 +3767,8 @@ struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
if (ns->head->ns_id == nsid) {
if (!nvme_get_ns(ns))
continue;
@@ -4851,7 +4852,8 @@ void nvme_mark_namespaces_dead(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
blk_mark_disk_dead(ns->disk);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
}
@@ -4863,7 +4865,8 @@ void nvme_unfreeze(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
blk_mq_unfreeze_queue(ns->queue);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
clear_bit(NVME_CTRL_FROZEN, &ctrl->flags);
@@ -4876,7 +4879,8 @@ int nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
timeout = blk_mq_freeze_queue_wait_timeout(ns->queue, timeout);
if (timeout <= 0)
break;
@@ -4892,7 +4896,8 @@ void nvme_wait_freeze(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
blk_mq_freeze_queue_wait(ns->queue);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
}
@@ -4905,7 +4910,8 @@ void nvme_start_freeze(struct nvme_ctrl *ctrl)
set_bit(NVME_CTRL_FROZEN, &ctrl->flags);
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
blk_freeze_queue_start(ns->queue);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
}
@@ -4953,7 +4959,8 @@ void nvme_sync_io_queues(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list)
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu))
blk_sync_queue(ns->queue);
srcu_read_unlock(&ctrl->srcu, srcu_idx);
}
---
base-commit: f488649e40f8900d23b86afeab7d4b78c063d5d1
change-id: 20241104-nvme_rcu-8250c60278e6
Best regards,
--
Breno Leitao <leitao@debian.org>
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] nvme/host: Fix RCU list traversal to use SRCU primitive
2024-11-04 12:24 [PATCH] nvme/host: Fix RCU list traversal to use SRCU primitive Breno Leitao
@ 2024-11-04 13:16 ` Christoph Hellwig
2024-11-04 21:26 ` Keith Busch
0 siblings, 1 reply; 3+ messages in thread
From: Christoph Hellwig @ 2024-11-04 13:16 UTC (permalink / raw)
To: Breno Leitao
Cc: Keith Busch, Jens Axboe, Christoph Hellwig, Sagi Grimberg,
linux-nvme, linux-kernel, kernel-team
On Mon, Nov 04, 2024 at 04:24:40AM -0800, Breno Leitao wrote:
> The code currently uses list_for_each_entry_rcu() while holding an SRCU
> lock, triggering false positive warnings with CONFIG_PROVE_RCU=y
> enabled:
>
> drivers/nvme/host/core.c:3770 RCU-list traversed in non-reader section!!
>
> While the list is properly protected by SRCU lock, the code uses the wrong
> list traversal primitive. Replace list_for_each_entry_rcu() with
> list_for_each_entry_srcu() to correctly indicate SRCU-based protection
> and eliminate the false warning.
I didn't even know there was such as thing as list_for_each_entry_srcu,
but apparently it's been there for a while. Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
> Something similar will need to be done for multipath. I will get it done
> once I get some feedback about this patch first.
Thanks!
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] nvme/host: Fix RCU list traversal to use SRCU primitive
2024-11-04 13:16 ` Christoph Hellwig
@ 2024-11-04 21:26 ` Keith Busch
0 siblings, 0 replies; 3+ messages in thread
From: Keith Busch @ 2024-11-04 21:26 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Breno Leitao, Jens Axboe, Sagi Grimberg, linux-nvme, linux-kernel,
kernel-team
On Mon, Nov 04, 2024 at 02:16:52PM +0100, Christoph Hellwig wrote:
> On Mon, Nov 04, 2024 at 04:24:40AM -0800, Breno Leitao wrote:
> > The code currently uses list_for_each_entry_rcu() while holding an SRCU
> > lock, triggering false positive warnings with CONFIG_PROVE_RCU=y
> > enabled:
> >
> > drivers/nvme/host/core.c:3770 RCU-list traversed in non-reader section!!
> >
> > While the list is properly protected by SRCU lock, the code uses the wrong
> > list traversal primitive. Replace list_for_each_entry_rcu() with
> > list_for_each_entry_srcu() to correctly indicate SRCU-based protection
> > and eliminate the false warning.
>
> I didn't even know there was such as thing as list_for_each_entry_srcu,
> but apparently it's been there for a while. Looks good:
Neither did I! Thanks Breno, applied to nvme-6.12
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-11-04 21:42 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-04 12:24 [PATCH] nvme/host: Fix RCU list traversal to use SRCU primitive Breno Leitao
2024-11-04 13:16 ` Christoph Hellwig
2024-11-04 21:26 ` Keith Busch
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox