Index | Thread | Search

From:
Vitaliy Makkoveev <mvs@openbsd.org>
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

Download raw body.

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