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


Reply via email to