Index | Thread | Search

From:
Martin Pieuchot <mpi@grenadille.net>
Subject:
Introduce uvm_promote()
To:
tech@openbsd.org
Date:
Wed, 18 Dec 2024 18:06:56 +0100

Download raw body.

Thread
Diff below merges two code paths that allocate a new anon and copy the
content of a page.

ok?

Index: uvm/uvm_fault.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_fault.c,v
diff -u -p -r1.154 uvm_fault.c
--- uvm/uvm_fault.c	18 Dec 2024 16:41:27 -0000	1.154
+++ uvm/uvm_fault.c	18 Dec 2024 17:00:56 -0000
@@ -485,6 +485,68 @@ uvmfault_anonget(struct uvm_faultinfo *u
 }
 
 /*
+ * uvmfault_promote: promote data to a new anon.  used for 1B and 2B.
+ *
+ *	1. allocate an anon and a page.
+ *	2. fill its contents.
+ *
+ * => if we fail (result != 0) we unlock everything.
+ * => on success, return a new locked anon via 'nanon'.
+ * => it's caller's responsibility to put the promoted nanon->an_page to the
+ *    page queue.
+ */
+int
+uvmfault_promote(struct uvm_faultinfo *ufi,
+    struct vm_page *uobjpage,
+    struct vm_anon **nanon, /* OUT: allocated anon */
+    struct vm_page **npg)
+{
+	struct vm_amap *amap = ufi->entry->aref.ar_amap;
+	struct vm_anon *anon;
+	struct vm_page *pg = NULL;
+
+	anon = uvm_analloc();
+	if (anon) {
+		anon->an_lock = amap->am_lock;
+		pg = uvm_pagealloc(NULL, 0, anon,
+		    (uobjpage == PGO_DONTCARE) ? UVM_PGA_ZERO : 0);
+	}
+
+	/* check for out of RAM */
+	if (anon == NULL || pg == NULL) {
+		uvmfault_unlockall(ufi, amap, NULL);
+		if (anon == NULL)
+			counters_inc(uvmexp_counters, flt_noanon);
+		else {
+			anon->an_lock = NULL;
+			anon->an_ref--;
+			uvm_anfree(anon);
+			counters_inc(uvmexp_counters, flt_noram);
+		}
+
+		if (uvm_swapisfull())
+			return ENOMEM;
+
+		/* out of RAM, wait for more */
+		if (anon == NULL)
+			uvm_anwait();
+		else
+			uvm_wait("flt_noram3");
+		return ERESTART;
+	}
+
+	/*
+	 * copy the page [pg now dirty]
+	 */
+	if (uobjpage != PGO_DONTCARE)
+		uvm_pagecopy(uobjpage, pg);
+
+	*nanon = anon;
+	*npg = pg;
+	return 0;
+}
+
+/*
  * Update statistics after fault resolution.
  * - maxrss
  */
@@ -972,37 +1034,11 @@ uvm_fault_upper(struct uvm_faultinfo *uf
 
 		counters_inc(uvmexp_counters, flt_acow);
 		oanon = anon;		/* oanon = old */
-		anon = uvm_analloc();
-		if (anon) {
-			anon->an_lock = amap->am_lock;
-			pg = uvm_pagealloc(NULL, 0, anon, 0);
-		}
-
-		/* check for out of RAM */
-		if (anon == NULL || pg == NULL) {
-			uvmfault_unlockall(ufi, amap, NULL);
-			if (anon == NULL)
-				counters_inc(uvmexp_counters, flt_noanon);
-			else {
-				anon->an_lock = NULL;
-				anon->an_ref--;
-				uvm_anfree(anon);
-				counters_inc(uvmexp_counters, flt_noram);
-			}
 
-			if (uvm_swapisfull())
-				return ENOMEM;
-
-			/* out of RAM, wait for more */
-			if (anon == NULL)
-				uvm_anwait();
-			else
-				uvm_wait("flt_noram3");
-			return ERESTART;
-		}
+		error = uvmfault_promote(ufi, oanon->an_page, &anon, &pg);
+		if (error)
+			return error;
 
-		/* got all resources, replace anon with nanon */
-		uvm_pagecopy(oanon->an_page, pg);	/* pg now !PG_CLEAN */
 		/* un-busy! new page */
 		atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE);
 		UVM_PAGE_OWN(pg, NULL);
@@ -1314,53 +1350,15 @@ uvm_fault_lower(struct uvm_faultinfo *uf
 		if (amap == NULL)
 			panic("uvm_fault: want to promote data, but no anon");
 #endif
-
-		anon = uvm_analloc();
-		if (anon) {
-			/*
-			 * In `Fill in data...' below, if
-			 * uobjpage == PGO_DONTCARE, we want
-			 * a zero'd, dirty page, so have
-			 * uvm_pagealloc() do that for us.
-			 */
-			anon->an_lock = amap->am_lock;
-			pg = uvm_pagealloc(NULL, 0, anon,
-			    (uobjpage == PGO_DONTCARE) ? UVM_PGA_ZERO : 0);
-		}
-
-		/*
-		 * out of memory resources?
-		 */
-		if (anon == NULL || pg == NULL) {
-			/* unlock and fail ... */
-			uvmfault_unlockall(ufi, amap, uobj);
-			if (anon == NULL)
-				counters_inc(uvmexp_counters, flt_noanon);
-			else {
-				anon->an_lock = NULL;
-				anon->an_ref--;
-				uvm_anfree(anon);
-				counters_inc(uvmexp_counters, flt_noram);
-			}
-
-			if (uvm_swapisfull())
-				return (ENOMEM);
-
-			/* out of RAM, wait for more */
-			if (anon == NULL)
-				uvm_anwait();
-			else
-				uvm_wait("flt_noram5");
-			return ERESTART;
-		}
+		error = uvmfault_promote(ufi, uobjpage, &anon, &pg);
+		if (error)
+			return error;
 
 		/*
 		 * fill in the data
 		 */
 		if (uobjpage != PGO_DONTCARE) {
 			counters_inc(uvmexp_counters, flt_prcopy);
-			/* copy page [pg now dirty] */
-			uvm_pagecopy(uobjpage, pg);
 
 			/*
 			 * promote to shared amap?  make sure all sharing