From: Vitaliy Makkoveev Subject: Re: KASSERT "uvmexp.swpgonly > 0" in uvm_anfree_list() To: miod@openbsd.org, robert@openbsd.org, tech@openbsd.org Date: Fri, 5 Apr 2024 18:38:04 +0300 On Fri, Apr 05, 2024 at 04:27:14PM +0200, Martin Pieuchot wrote: > Many over the past months have reported this assertion in different > scenarios. All of them involved swapping some pages. > > I figured out that it is due to an accounting bug in uvm_anon_release(). > When that function is called, the given anon has a page attached and it > might also have an allocated swap slot. > > The accounting bugs occurs only when an anon has such allocated swap slot. > In such case the wrong path is taken inside uvm_anfree() because `an_page' > has been cleared by uvm_pagefree() and the global `uvmexp.swpgonly' counter > is decremented. > > Diff below fixes it. Ok? > > Index: uvm/uvm_anon.c > =================================================================== > RCS file: /cvs/src/sys/uvm/uvm_anon.c,v > diff -u -p -r1.57 uvm_anon.c > --- uvm/uvm_anon.c 27 Oct 2023 19:13:51 -0000 1.57 > +++ uvm/uvm_anon.c 31 Mar 2024 06:49:40 -0000 > @@ -260,7 +260,8 @@ uvm_anon_release(struct vm_anon *anon) > uvm_unlock_pageq(); > KASSERT(anon->an_page == NULL); > lock = anon->an_lock; > - uvm_anfree(anon); > + uvm_anon_dropswap(anon); > + pool_put(&uvm_anon_pool, anon); > rw_exit(lock); > /* Note: extra reference is held for PG_RELEASED case. */ > rw_obj_free(lock); > In my cases, this assertion was triggered with my sysctl(2) unlocking diff running on i386 machine. I have ho hardware to test it. Feel free to ask me, I'll rework sysctl(2) diff if required.