Re: [PATCH v2] nvme: remove stale namespaces by NSID range during scan

Mohamed Khalfella <[email protected]>
Newsgroups org.infradead.lists.linux-nvme,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On Mon 2026-08-24 17:21:26 -0700, Randy Jennings wrote:
> On Sat, Aug 22, 2026 at 5:47 PM Mohamed Khalfella
> <[email protected]> wrote:
> >
> > nvme_scan_ns_list() drops the stale namespaces in each gap in the
> > reported NSID list one NSID at a time. Every iteration calls
> > nvme_find_get_ns() to look the namespace up and removes it if it is
> > present. The loop runs once per NSID in the gap rather than once per
> > namespace actually present.
> >
> > NSIDs are 32-bit, so a target with a sparse NSID space can make a
> > single gap spin the loop billions of times with nothing to remove.
> >
> >   watchdog: BUG: soft lockup - CPU#4 stuck for 26s!
> >   Workqueue: nvme-wq nvme_scan_work [nvme_core]
> >   RIP: 0010:__srcu_read_unlock+0xb/0x20
> >   Call Trace:
> >    nvme_find_get_ns+0x7d/0xb0 [nvme_core]
> >    nvme_scan_ns_list+0xe8/0x280 [nvme_core]
> >    nvme_scan_work+0x18a/0x280 [nvme_core]
> >    process_one_work+0x197/0x380
> >    worker_thread+0x2fe/0x410
> >    kthread+0xe0/0x100
> >
> > Rename nvme_remove_invalid_namespaces() to nvme_remove_nsid_range()
> > and give it an open (start, end) NSID range. ctrl->namespaces is
> > sorted by NSID, so the whole gap is dropped in a single walk that
> > stops once end is reached. This bounds the work by the namespaces
> > that are present instead of by the size of the gap.
> >
> > Fixes: 540c801c65eb ("NVMe: Implement namespace list scanning")
> > Signed-off-by: Mohamed Khalfella <[email protected]>
> > Reviewed-by: Sagi Grimberg <[email protected]>
> Reviewed-by: Randy Jennings <[email protected]>
> 
> > ---
> >  drivers/nvme/host/core.c | 18 +++++++++---------
> 
> > -static void nvme_remove_invalid_namespaces(struct nvme_ctrl *ctrl,
> > -                                       unsigned nsid)
> > +static void nvme_remove_nsid_range(struct nvme_ctrl *ctrl, u32 start, u32 end)
> It is not intuitive to me that start is non-inclusive.  May we add
> a comment to that effect?

Yes, it is not intuitive. [start, end) makes more sense IMO. That is
said, this is how nvme_remove_invalid_namespaces() worked and I decided
not to change that because it is not part of the fix. I do not think a
comment will make a big difference here. The next person who works on
this code will read the nvme_remove_nsid_range(), it is a short
function, and figure out how it works.

> 
> >  {
> >         struct nvme_ns *ns, *next;
> >         LIST_HEAD(rm_list);
> >
> >         mutex_lock(&ctrl->namespaces_lock);
> >         list_for_each_entry_safe(ns, next, &ctrl->namespaces, list) {
> > -               if (ns->head->ns_id > nsid) {
> > +               if (ns->head->ns_id >= end)
> > +                       break;
> > +               if (ns->head->ns_id > start) {
> >                         list_del_rcu(&ns->list);
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.