That is quite a bug.
A few things aren't stated in the mail.
Is this very old? Or is it new?
Who broke it?
Who tested it?
Who ok'd it?
Was it tested enough?
Was it tested in enough environmnents by enough people?
I'd like to encourage everyone who was involved in this to answer those
questions honestly.
Thank you.
> On 27/12/25(Sat) 18:15, Alexander Bluhm wrote:
> > On Sat, Dec 27, 2025 at 10:26:58AM +0100, Martin Pieuchot wrote:
> > > On 26/12/25(Fri) 13:36, Alexander Bluhm wrote:
> > > > On Fri, Dec 26, 2025 at 01:02:17PM +0100, Alexander Bluhm wrote:
> > > > > Anyway. Currently I cannot reproduce. I will keep an eye on it.
> > > > > I will use the diff below if it happens again.
> > > >
> > > > And just after writing this, I hit the crash.
> > >
> > > Thanks Alexander, so this confirms the race with uvm_pagefree().
> > >
> > > Here's the full diff. Would you please try to reproduce the panic with
> > > it and hopefully report the next bug?
> >
> > Here we go
>
> Thanks a lot Alexander, here's a proper fix. We need to use an iterator
> when scanning the active loop because it releases the pageqlock.
> Without iterator 'nextpg' might no longer be on the list or it might be
> on the list but somewhere else.
>
> Diff below uses the same logic already present in the inactive loop. Do
> you see a different panic with it?
>
> Index: uvm/uvm_pdaemon.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_pdaemon.c,v
> diff -u -p -r1.144 uvm_pdaemon.c
> --- uvm/uvm_pdaemon.c 24 Dec 2025 10:29:22 -0000 1.144
> +++ uvm/uvm_pdaemon.c 29 Dec 2025 16:13:20 -0000
> @@ -923,15 +923,18 @@ void
> uvmpd_scan_active(struct uvm_pmalloc *pma, int swap_shortage,
> int inactive_shortage)
> {
> - struct vm_page *p, *nextpg;
> + struct pglist *pglst = &uvm.page_active;
> + struct vm_page *p, iter = { .pg_flags = PQ_ITER };
> struct rwlock *slock;
>
> MUTEX_ASSERT_LOCKED(&uvm.pageqlock);
>
> - for (p = TAILQ_FIRST(&uvm.page_active);
> - p != NULL && (inactive_shortage > 0 || swap_shortage > 0);
> - p = nextpg) {
> - nextpg = TAILQ_NEXT(p, pageq);
> + p = TAILQ_FIRST(pglst);
> +
> + /* Insert iterator. */
> + TAILQ_INSERT_AFTER(pglst, p, &iter, pageq);
> + for (; p != NULL && (inactive_shortage > 0 || swap_shortage > 0);
> + p = uvmpd_iterator(pglst, p, &iter)) {
> if (p->pg_flags & PG_BUSY) {
> continue;
> }
> @@ -993,6 +996,7 @@ uvmpd_scan_active(struct uvm_pmalloc *pm
> */
> rw_exit(slock);
> }
> + TAILQ_REMOVE(pglst, &iter, pageq);
> }
>
> #ifdef HIBERNATE
>
>