From: Mark Kettenis Subject: Re: KASSERT "uvmexp.swpgonly > 0" in uvm_anfree_list() To: Martin Pieuchot Cc: mvs@openbsd.org, miod@openbsd.org, robert@openbsd.org, tech@openbsd.org Date: Fri, 05 Apr 2024 17:35:04 +0200 > Date: Fri, 5 Apr 2024 16:27:14 +0200 > From: Martin Pieuchot > > 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? ok kettenis@ > 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); > >