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