Module Name:    src
Committed By:   uebayasi
Date:           Mon Feb  1 16:08:27 UTC 2010

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

Log Message:
More split.


To generate a diff of this commit:
cvs rdiff -u -r1.147 -r1.148 src/sys/uvm/uvm_fault.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_fault.c
diff -u src/sys/uvm/uvm_fault.c:1.147 src/sys/uvm/uvm_fault.c:1.148
--- src/sys/uvm/uvm_fault.c:1.147	Mon Feb  1 11:58:39 2010
+++ src/sys/uvm/uvm_fault.c	Mon Feb  1 16:08:27 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_fault.c,v 1.147 2010/02/01 11:58:39 uebayasi Exp $	*/
+/*	$NetBSD: uvm_fault.c,v 1.148 2010/02/01 16:08:27 uebayasi Exp $	*/
 
 /*
  *
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.147 2010/02/01 11:58:39 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.148 2010/02/01 16:08:27 uebayasi Exp $");
 
 #include "opt_uvmhist.h"
 
@@ -713,7 +713,6 @@
     struct uvm_faultinfo *, struct uvm_faultctx *,
     struct vm_anon **, struct vm_page **);
 static uvm_fault_upper_subfunc_t uvm_fault_upper_lookup;
-static uvm_fault_upper_subfunc_t uvm_fault_upper;
 typedef int uvm_fault_lower_subfunc_t(
     struct uvm_faultinfo *, struct uvm_faultctx *,
     struct vm_page **);
@@ -721,8 +720,15 @@
 static uvm_fault_lower_subfunc_t uvm_fault_lower_special;
 static uvm_fault_lower_subfunc_t uvm_fault_lower_generic_lookup;
 static uvm_fault_lower_subfunc_t uvm_fault_lower_generic;
-static uvm_fault_lower_subfunc_t uvm_fault_lower_generic1;
-static uvm_fault_lower_subfunc_t uvm_fault_lower_generic2;
+static int uvm_fault_upper(
+    struct uvm_faultinfo *, struct uvm_faultctx *,
+    struct vm_anon **);
+static int uvm_fault_lower_generic1(
+    struct uvm_faultinfo *, struct uvm_faultctx *,
+    struct vm_page *);
+static int uvm_fault_lower_generic2(
+    struct uvm_faultinfo *, struct uvm_faultctx *,
+    struct vm_page *);
 
 int
 uvm_fault_internal(struct vm_map *orig_map, vaddr_t vaddr,
@@ -773,7 +779,7 @@
 			continue;
 
 		if (pages[flt.centeridx] == PGO_DONTCARE)
-			error = uvm_fault_upper(&ufi, &flt, anons, pages);
+			error = uvm_fault_upper(&ufi, &flt, anons);
 		else
 			error = uvm_fault_lower(&ufi, &flt, pages);
 	}
@@ -1167,7 +1173,7 @@
 	} else {
 		uvm_fault_lower_generic_lookup(ufi, flt, pages);
 	}
-	return uvm_fault_lower_generic1(ufi, flt, pages);
+	return uvm_fault_lower_generic1(ufi, flt, pages[flt->centeridx]);
 }
 
 static int
@@ -1275,12 +1281,11 @@
 static int
 uvm_fault_lower_generic1(
 	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
-	struct vm_page **pages)
+	struct vm_page *uobjpage)
 {
 #ifdef DIAGNOSTIC
 	struct vm_amap *amap = ufi->entry->aref.ar_amap;
 	struct uvm_object *uobj = ufi->entry->object.uvm_obj;
-	struct vm_page *uobjpage = pages[flt->centeridx];
 #endif
 
 	/* locked: maps(read), amap(if there), uobj(if !null), uobjpage(if !null) */
@@ -1307,17 +1312,44 @@
 	 * redirect case 2: if we are not shadowed, go to case 2.
 	 */
 
-	return uvm_fault_lower_generic2(ufi, flt, pages);
+	return uvm_fault_lower_generic2(ufi, flt, uobjpage);
 }
 
 static int
+uvm_fault_upper_loan(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_anon *anon, struct uvm_object **ruobj);
+static int
+uvm_fault_upper1(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon);
+static int
+uvm_fault_upper_promote(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon);
+static int
+uvm_fault_upper_direct(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon);
+static int
+uvm_fault_upper_enter(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon,
+	struct vm_page *pg, struct vm_anon *oanon);
+static int
+uvm_fault_upper_done(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon,
+	struct vm_page *pg, struct vm_anon *oanon);
+
+static int
 uvm_fault_upper(
 	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
-	struct vm_anon **anons, struct vm_page **pages)
+	struct vm_anon **anons)
 {
-	struct vm_amap *amap = ufi->entry->aref.ar_amap;
-	struct uvm_object *uobj = ufi->entry->object.uvm_obj;
-	struct vm_anon *anon, *oanon;
+	struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+	struct vm_anon * const anon = anons[flt->centeridx];
+	struct uvm_object *uobj;
 	int error;
 
 	/* locked: maps(read), amap */
@@ -1327,7 +1359,6 @@
 	 * handle case 1: fault on an anon in our amap
 	 */
 
-	anon = anons[flt->centeridx];
 	UVMHIST_LOG(maphist, "  case 1 fault: anon=0x%x", anon, 0,0,0);
 	mutex_enter(&anon->an_lock);
 
@@ -1381,6 +1412,20 @@
 	 */
 
 	if (anon->an_page->loan_count) {
+		error = uvm_fault_upper_loan(ufi, flt, anon, &uobj);
+		if (error != 0)
+			return error;
+	}
+	return uvm_fault_upper1(ufi, flt, uobj, anon);
+}
+
+static int
+uvm_fault_upper_loan(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_anon *anon, struct uvm_object **ruobj)
+{
+		struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+		struct uvm_object *uobj = *ruobj;
 
 		if (!flt->cow_now) {
 
@@ -1446,7 +1491,7 @@
 
 				if (uobj) {
 					mutex_exit(&uobj->vmobjlock);
-					uobj = NULL;
+					*ruobj = NULL;
 				}
 
 				/* install new page in anon */
@@ -1463,7 +1508,16 @@
 				/* done! */
 			}     /* ref == 1 */
 		}       /* write fault */
-	}         /* loan count */
+
+		return 0;
+}
+
+static int
+uvm_fault_upper1(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon)
+{
+	int error;
 
 	/*
 	 * if we are case 1B then we will need to allocate a new blank
@@ -1478,12 +1532,25 @@
 	 * if we are out of anon VM we kill the process (XXX: could wait?).
 	 */
 
-	struct vm_page *pg;
 	if (flt->cow_now && anon->an_ref > 1) {
+		error = uvm_fault_upper_promote(ufi, flt, uobj, anon);
+	} else {
+		error = uvm_fault_upper_direct(ufi, flt, uobj, anon);
+	}
+	return error;
+}
+
+static int
+uvm_fault_upper_promote(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon)
+{
+		struct vm_anon * const oanon = anon;
+		struct vm_page *pg;
+		int error;
 
 		UVMHIST_LOG(maphist, "  case 1B: COW fault",0,0,0,0);
 		uvmexp.flt_acow++;
-		oanon = anon;		/* oanon = old, locked anon */
 
 		error = uvmfault_promote(ufi, oanon, PGO_DONTCARE,
 		    &anon, &flt->anon_spare);
@@ -1512,15 +1579,32 @@
 		 * oanon != anon, we'll have to unlock anon, too.
 		 */
 
-	} else {
+		return uvm_fault_upper_enter(ufi, flt, uobj, anon, pg, oanon);
+}
+
+static int
+uvm_fault_upper_direct(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon)
+{
+		struct vm_anon * const oanon = anon;
+		struct vm_page *pg;
 
 		uvmexp.flt_anon++;
-		oanon = anon;		/* old, locked anon is same as anon */
 		pg = anon->an_page;
 		if (anon->an_ref > 1)     /* disallow writes to ref > 1 anons */
 			flt->enter_prot = flt->enter_prot & ~VM_PROT_WRITE;
 
-	}
+		return uvm_fault_upper_enter(ufi, flt, uobj, anon, pg, oanon);
+}
+
+static int
+uvm_fault_upper_enter(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon, struct vm_page *pg,
+	struct vm_anon *oanon)
+{
+	struct vm_amap * const amap = ufi->entry->aref.ar_amap;
 
 	/* locked: maps(read), amap, oanon, anon (if different from oanon) */
 	KASSERT(mutex_owned(&amap->am_l));
@@ -1552,14 +1636,24 @@
 			UVMHIST_LOG(maphist,
 			    "<- failed.  out of VM",0,0,0,0);
 			/* XXX instrumentation */
-			error = ENOMEM;
-			return error;
+			return ENOMEM;
 		}
 		/* XXX instrumentation */
 		uvm_wait("flt_pmfail1");
 		return ERESTART;
 	}
 
+	return uvm_fault_upper_done(ufi, flt, uobj, anon, pg, oanon);
+}
+
+static int
+uvm_fault_upper_done(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon,
+	struct vm_page *pg, struct vm_anon *oanon)
+{
+	struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+
 	/*
 	 * ... update the page queues.
 	 */
@@ -1594,14 +1688,41 @@
 }
 
 static int
+uvm_fault_lower_generic_io(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_page **ruobjpage);
+static int
+uvm_fault_lower_generic_uobjpage(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_page *uobjpage, bool promote);
+static int
+uvm_fault_lower_generic_direct(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_page *uobjpage);
+static int
+uvm_fault_lower_generic_promote(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_page *uobjpage);
+static int
+uvm_fault_lower_generic_enter(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj,
+	struct vm_anon *anon, struct vm_page *pg, struct vm_page *uobjpage);
+static int
+uvm_fault_lower_generic_done(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj,
+	struct vm_anon *anon, struct vm_page *pg);
+
+static int
 uvm_fault_lower_generic2(
 	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
-	struct vm_page **pages)
+	struct vm_page *uobjpage)
 {
-	struct vm_amap *amap = ufi->entry->aref.ar_amap;
-	struct uvm_object *uobj = ufi->entry->object.uvm_obj;
-	struct vm_page *uobjpage = pages[flt->centeridx];
-	struct vm_anon *anon;
+#ifdef DIAGNOSTIC
+	struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+#endif
+	struct uvm_object * const uobj = ufi->entry->object.uvm_obj;
 	bool promote;
 	int error;
 
@@ -1647,8 +1768,24 @@
 		/* update rusage counters */
 		curlwp->l_ru.ru_minflt++;
 	} else {
+		error = uvm_fault_lower_generic_io(ufi, flt, &uobjpage);
+		if (error != 0)
+			return error;
+	}
+	return uvm_fault_lower_generic_uobjpage(ufi, flt, uobjpage, promote);
+}
+
+static int
+uvm_fault_lower_generic_io(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_page **ruobjpage)
+{
+		struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+		struct uvm_object * const uobj = ufi->entry->object.uvm_obj;
+		struct vm_page *uobjpage;
 		bool locked;
 		int gotpages;
+		int error;
 		voff_t uoff;
 
 		/* update rusage counters */
@@ -1706,7 +1843,7 @@
 		locked = uvmfault_relock(ufi);
 		if (locked && amap)
 			amap_lock(amap);
-		uobj = uobjpage->uobject;
+		KASSERT(uobj == uobjpage->uobject);
 		mutex_enter(&uobj->vmobjlock);
 
 		/* locked(locked): maps(read), amap(if !null), uobj, uobjpage */
@@ -1755,7 +1892,21 @@
 		 */
 
 		/* locked: maps(read), amap(if !null), uobj, uobjpage */
-	}
+
+	*ruobjpage = uobjpage;
+	return 0;
+}
+
+int
+uvm_fault_lower_generic_uobjpage(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_page *uobjpage, bool promote)
+{
+#ifdef DIAGNOSTIC
+	struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+	struct uvm_object * const uobj = ufi->entry->object.uvm_obj;
+#endif
+	int error;
 
 	/*
 	 * locked:
@@ -1776,8 +1927,23 @@
 	KASSERT(uobj == NULL || uobj == uobjpage->uobject);
 	KASSERT(uobj == NULL || !UVM_OBJ_IS_CLEAN(uobjpage->uobject) ||
 	    (uobjpage->flags & PG_CLEAN) != 0);
-	struct vm_page *pg;
+
 	if (promote == false) {
+		error = uvm_fault_lower_generic_direct(ufi, flt, uobjpage);
+	} else {
+		error = uvm_fault_lower_generic_promote(ufi, flt, uobjpage);
+	}
+	return error;
+}
+
+int
+uvm_fault_lower_generic_direct(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_page *uobjpage)
+{
+		struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+		struct uvm_object * const uobj = ufi->entry->object.uvm_obj;
+		struct vm_page *pg;
 
 		/*
 		 * we are not promoting.   if the mapping is COW ensure that we
@@ -1788,9 +1954,6 @@
 		 * set "pg" to the page we want to map in (uobjpage, usually)
 		 */
 
-		/* no anon in this case. */
-		anon = NULL;
-
 		uvmexp.flt_obj++;
 		if (UVM_ET_ISCOPYONWRITE(ufi->entry) ||
 		    UVM_OBJ_NEEDS_WRITEFAULT(uobjpage->uobject))
@@ -1837,7 +2000,20 @@
 				uobjpage = pg;
 			}
 		}
-	} else {
+
+	return uvm_fault_lower_generic_enter(ufi, flt, uobj, NULL, pg, uobjpage);
+}
+
+int
+uvm_fault_lower_generic_promote(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct vm_page *uobjpage)
+{
+		struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+		struct uvm_object *uobj = ufi->entry->object.uvm_obj;
+		struct vm_anon *anon;
+		struct vm_page *pg;
+		int error;
 
 		/*
 		 * if we are going to promote the data to an anon we
@@ -1908,7 +2084,18 @@
 			UVMHIST_LOG(maphist,"  zero fill anon/page 0x%x/0%x",
 			    anon, pg, 0, 0);
 		}
-	}
+
+	return uvm_fault_lower_generic_enter(ufi, flt, uobj, anon, pg, uobjpage);
+}
+
+int
+uvm_fault_lower_generic_enter(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj,
+	struct vm_anon *anon, struct vm_page *pg, struct vm_page *uobjpage)
+{
+	struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+	int error;
 
 	/*
 	 * locked:
@@ -1969,6 +2156,16 @@
 		return ERESTART;
 	}
 
+	return uvm_fault_lower_generic_done(ufi, flt, uobj, anon, pg);
+}
+
+int
+uvm_fault_lower_generic_done(
+	struct uvm_faultinfo *ufi, struct uvm_faultctx *flt,
+	struct uvm_object *uobj, struct vm_anon *anon, struct vm_page *pg)
+{
+	struct vm_amap * const amap = ufi->entry->aref.ar_amap;
+
 	mutex_enter(&uvm_pageqlock);
 	if (flt->wire_paging) {
 		uvm_pagewire(pg);

Reply via email to