On Mon, Dec 29, 2025 at 05:23:12PM +0100, Martin Pieuchot wrote:
> 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?

Passed make build on the affected i386 machine twice
Passed regress on i386
Passed regress with witness on amd64

OK bluhm@

> 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
> 

Reply via email to