Module Name:    src
Committed By:   chs
Date:           Tue Aug 18 10:40:20 UTC 2020

Modified Files:
        src/sys/uvm: uvm_amap.c

Log Message:
fix amap_extend() to handle amaps where we previously failed to allocate
the ppref memory.


To generate a diff of this commit:
cvs rdiff -u -r1.122 -r1.123 src/sys/uvm/uvm_amap.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/uvm/uvm_amap.c
diff -u src/sys/uvm/uvm_amap.c:1.122 src/sys/uvm/uvm_amap.c:1.123
--- src/sys/uvm/uvm_amap.c:1.122	Thu Jul  9 05:57:15 2020
+++ src/sys/uvm/uvm_amap.c	Tue Aug 18 10:40:20 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_amap.c,v 1.122 2020/07/09 05:57:15 skrll Exp $	*/
+/*	$NetBSD: uvm_amap.c,v 1.123 2020/08/18 10:40:20 chs Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.122 2020/07/09 05:57:15 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.123 2020/08/18 10:40:20 chs Exp $");
 
 #include "opt_uvmhist.h"
 
@@ -353,7 +353,7 @@ amap_extend(struct vm_map_entry *entry, 
 	struct vm_amap *amap = entry->aref.ar_amap;
 	int slotoff = entry->aref.ar_pageoff;
 	int slotmapped, slotadd, slotneed, slotadded, slotalloc;
-	int slotadj, slotarea;
+	int slotadj, slotarea, slotendoff;
 	int oldnslots;
 #ifdef UVM_AMAP_PPREF
 	int *newppref, *oldppref;
@@ -388,6 +388,36 @@ amap_extend(struct vm_map_entry *entry, 
 	}
 
 	/*
+	 * Because this amap only has 1 ref, we know that there is
+	 * only one vm_map_entry pointing to it, and the one entry is
+	 * using slots between slotoff and slotoff + slotmapped.  If
+	 * we have been using ppref then we know that only slots in
+	 * the one map entry's range can have anons, since ppref
+	 * allowed us to free any anons outside that range as other map
+	 * entries which used this amap were removed. But without ppref,
+	 * we couldn't know which slots were still needed by other map
+	 * entries, so we couldn't free any anons as we removed map
+	 * entries, and so any slot from 0 to am_nslot can have an
+	 * anon.  But now that we know there is only one map entry
+	 * left and we know its range, we can free up any anons
+	 * outside that range.  This is necessary because the rest of
+	 * this function assumes that there are no anons in the amap
+	 * outside of the one map entry's range.
+	 */
+
+	slotendoff = slotoff + slotmapped;
+	if (amap->am_ppref == PPREF_NONE) {
+		amap_wiperange(amap, 0, slotoff);
+		amap_wiperange(amap, slotendoff, amap->am_nslot - slotendoff);
+	}
+	for (i = 0; i < slotoff; i++) {
+		KASSERT(amap->am_anon[i] == NULL);
+	}
+	for (i = slotendoff; i < amap->am_nslot - slotendoff; i++) {
+		KASSERT(amap->am_anon[i] == NULL);
+	}
+
+	/*
 	 * case 1: we already have enough slots in the map and thus
 	 * only need to bump the reference counts on the slots we are
 	 * adding.

Reply via email to