Index | Thread | Search

From:
Martin Pieuchot <mpi@openbsd.org>
Subject:
KASSERT "uvmexp.swpgonly > 0" in uvm_anfree_list()
To:
mvs@openbsd.org, miod@openbsd.org, robert@openbsd.org
Cc:
tech@openbsd.org
Date:
Fri, 5 Apr 2024 16:27:14 +0200

Download raw body.

Thread
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);