Re: [PATCH] nvme-pci: add adaptive interrupt polling

"changfengnan" <[email protected]>
Newsgroups org.infradead.lists.linux-nvme,org.kernel.vger.linux-kernel
Message-ID <d9210bcdf73fbe1ac8b6ec132865609a3ed68688.f73839cb.7360.4530.9912.75608111828b@bytedance.com>
> From: "Anuj Gupta"<[email protected]>
> Date:  Tue, Aug 25, 2026, 10:59
> Subject:  Re: [PATCH] nvme-pci: add adaptive interrupt polling
> To: "Fengnan Chang"<[email protected]>
> Cc: "Keith Busch"<[email protected]>, "Jens Axboe"<[email protected]>, "Christoph Hellwig"<[email protected]>, "Sagi Grimberg"<[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, "Guzebing"<[email protected]>, <[email protected]>
> > +/*
> > + * Drain CQEs from IRQ_POLL_SOFTIRQ and compare completion progress with the
> > + * IRQ baseline.  Re-arm while within the allowed lag; leave poll mode on lag
> > + * or teardown, and start another window only after a faster full window.
> > + */
> > +static int nvme_adaptive_irq_poll(struct irq_poll *iop, int budget)
> > +{
> > +        struct nvme_adaptive_poll *adaptive = container_of(iop,
> > +                                        struct nvme_adaptive_poll, iopoll);
> > +        struct nvme_queue *nvmeq = adaptive->nvmeq;
> > +        unsigned int completions, limit;
> > +        unsigned long flags;
> > +        u64 deadline, elapsed, now;
> > +        DEFINE_IO_COMP_BATCH(iob);
> > +
> > +        spin_lock_irqsave(&nvmeq->cq_poll_lock, flags);
> > +        if (unlikely(!test_bit(NVMEQ_ADAPTIVE_POLLING, &nvmeq->flags))) {
> > +                completions = 0;
> > +                irq_poll_complete(iop);
> > +                goto out;
> > +        }
> > +        if (!test_bit(NVMEQ_ENABLED, &nvmeq->flags)) {
> > +                completions = 0;
> > +                irq_poll_complete(iop);
> > +                nvme_adaptive_poll_end(nvmeq, false);
> > +                goto out;
> > +        }
> > +
> > +        limit = min_t(unsigned int,
> > +                      budget,
> > +                      NVME_ADAPTIVE_EPISODE_CQES - adaptive->completions);
> > +        completions = nvme_poll_cq_bounded(nvmeq, &iob, limit);
> > +        adaptive->completions += completions;
> > +
> > +        if (completions >= budget &&
> > +            adaptive->completions < NVME_ADAPTIVE_EPISODE_CQES)
> > +                goto out;
> > +        irq_poll_complete(iop);
> 
> If the last drain reaches NVME_ADAPTIVE_EPISODE_CQES with
> completions == budget, this calls irq_poll_complete() but still returns
> budget. irq_poll_softirq() will then call list_move_tail() on an entry
> that has already been removed.

Thanks, you are right, I also noticed this issue during testing.
In next version, irq_poll_complete() is called only when
completions < budget, so a full-budget return leaves the iopoll state untouched.

> Should the full-budget case always goto out and let the next invocation
> complete and evaluate the episode?
> 
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.