Module Name:    src
Committed By:   rmind
Date:           Sat May 29 23:17:53 UTC 2010

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

Log Message:
ubc_fault: split-off code part handling a single page into ubc_fault_page().


To generate a diff of this commit:
cvs rdiff -u -r1.68 -r1.69 src/sys/uvm/uvm_bio.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_bio.c
diff -u src/sys/uvm/uvm_bio.c:1.68 src/sys/uvm/uvm_bio.c:1.69
--- src/sys/uvm/uvm_bio.c:1.68	Sat Nov  7 07:27:49 2009
+++ src/sys/uvm/uvm_bio.c	Sat May 29 23:17:53 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_bio.c,v 1.68 2009/11/07 07:27:49 cegger Exp $	*/
+/*	$NetBSD: uvm_bio.c,v 1.69 2010/05/29 23:17:53 rmind Exp $	*/
 
 /*
  * Copyright (c) 1998 Chuck Silvers.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.68 2009/11/07 07:27:49 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_bio.c,v 1.69 2010/05/29 23:17:53 rmind Exp $");
 
 #include "opt_uvmhist.h"
 #include "opt_ubc.h"
@@ -216,6 +216,91 @@
 }
 
 /*
+ * ubc_fault_page: helper of ubc_fault to handle a single page.
+ */
+
+static inline void
+ubc_fault_page(const struct uvm_faultinfo *ufi, const struct ubc_map *umap,
+    struct vm_page *pg, vm_prot_t prot, vm_prot_t access_type, vaddr_t va)
+{
+	struct uvm_object *uobj;
+	vm_prot_t mask;
+	int error;
+	bool rdonly;
+
+	uobj = pg->uobject;
+	mutex_enter(&uobj->vmobjlock);
+	if (pg->flags & PG_WANTED) {
+		wakeup(pg);
+	}
+	KASSERT((pg->flags & PG_FAKE) == 0);
+	if (pg->flags & PG_RELEASED) {
+		mutex_enter(&uvm_pageqlock);
+		uvm_pagefree(pg);
+		mutex_exit(&uvm_pageqlock);
+		mutex_exit(&uobj->vmobjlock);
+		return;
+	}
+	if (pg->loan_count != 0) {
+
+		/*
+		 * Avoid unneeded loan break, if possible.
+		 */
+
+		if ((access_type & VM_PROT_WRITE) == 0) {
+			prot &= ~VM_PROT_WRITE;
+		}
+		if (prot & VM_PROT_WRITE) {
+			struct vm_page *newpg;
+
+			newpg = uvm_loanbreak(pg);
+			if (newpg == NULL) {
+				uvm_page_unbusy(&pg, 1);
+				mutex_exit(&uobj->vmobjlock);
+				uvm_wait("ubc_loanbrk");
+				/*
+				 * Note: will re-fault.
+				 */
+				return;
+			}
+			pg = newpg;
+		}
+	}
+
+	/*
+	 * Note that a page whose backing store is partially allocated
+	 * is marked as PG_RDONLY.
+	 */
+
+	KASSERT((pg->flags & PG_RDONLY) == 0 ||
+	    (access_type & VM_PROT_WRITE) == 0 ||
+	    pg->offset < umap->writeoff ||
+	    pg->offset + PAGE_SIZE > umap->writeoff + umap->writelen);
+
+	rdonly = ((access_type & VM_PROT_WRITE) == 0 &&
+	    (pg->flags & PG_RDONLY) != 0) ||
+	    UVM_OBJ_NEEDS_WRITEFAULT(uobj);
+	mask = rdonly ? ~VM_PROT_WRITE : VM_PROT_ALL;
+
+	error = pmap_enter(ufi->orig_map->pmap, va, VM_PAGE_TO_PHYS(pg),
+	    prot & mask, PMAP_CANFAIL | (access_type & mask));
+
+	mutex_enter(&uvm_pageqlock);
+	uvm_pageactivate(pg);
+	mutex_exit(&uvm_pageqlock);
+	pg->flags &= ~(PG_BUSY|PG_WANTED);
+	UVM_PAGE_OWN(pg, NULL);
+	mutex_exit(&uobj->vmobjlock);
+
+	if (error) {
+		/*
+		 * Note: will re-fault.
+		 */
+		uvm_wait("ubc_pmfail");
+	}
+}
+
+/*
  * ubc_fault: fault routine for ubc mapping
  */
 
@@ -226,10 +311,11 @@
 	struct uvm_object *uobj;
 	struct ubc_map *umap;
 	vaddr_t va, eva, ubc_offset, slot_offset;
+	struct vm_page *pgs[ubc_winsize >> PAGE_SHIFT];
 	int i, error, npages;
-	struct vm_page *pgs[ubc_winsize >> PAGE_SHIFT], *pg;
 	vm_prot_t prot;
-	UVMHIST_FUNC("ubc_fault");  UVMHIST_CALLED(ubchist);
+
+	UVMHIST_FUNC("ubc_fault"); UVMHIST_CALLED(ubchist);
 
 	/*
 	 * no need to try with PGO_LOCKED...
@@ -307,97 +393,32 @@
 		return error;
 	}
 
+	/*
+	 * For virtually-indexed, virtually-tagged caches we should avoid
+	 * creating writable mappings when we do not absolutely need them,
+	 * since the "compatible alias" trick does not work on such caches.
+	 * Otherwise, we can always map the pages writable.
+	 */
+
+#ifdef PMAP_CACHE_VIVT
+	prot = VM_PROT_READ | access_type;
+#else
+	prot = VM_PROT_READ | VM_PROT_WRITE;
+#endif
 	va = ufi->orig_rvaddr;
 	eva = ufi->orig_rvaddr + (npages << PAGE_SHIFT);
 
 	UVMHIST_LOG(ubchist, "va 0x%lx eva 0x%lx", va, eva, 0, 0);
 	for (i = 0; va < eva; i++, va += PAGE_SIZE) {
-		bool rdonly;
-		vm_prot_t mask;
+		struct vm_page *pg;
 
-		/*
-		 * for virtually-indexed, virtually-tagged caches we should
-		 * avoid creating writable mappings when we don't absolutely
-		 * need them, since the "compatible alias" trick doesn't work
-		 * on such caches.  otherwise, we can always map the pages
-		 * writable.
-		 */
-
-#ifdef PMAP_CACHE_VIVT
-		prot = VM_PROT_READ | access_type;
-#else
-		prot = VM_PROT_READ | VM_PROT_WRITE;
-#endif
 		UVMHIST_LOG(ubchist, "pgs[%d] = %p", i, pgs[i], 0, 0);
 		pg = pgs[i];
 
 		if (pg == NULL || pg == PGO_DONTCARE) {
 			continue;
 		}
-
-		uobj = pg->uobject;
-		mutex_enter(&uobj->vmobjlock);
-		if (pg->flags & PG_WANTED) {
-			wakeup(pg);
-		}
-		KASSERT((pg->flags & PG_FAKE) == 0);
-		if (pg->flags & PG_RELEASED) {
-			mutex_enter(&uvm_pageqlock);
-			uvm_pagefree(pg);
-			mutex_exit(&uvm_pageqlock);
-			mutex_exit(&uobj->vmobjlock);
-			continue;
-		}
-		if (pg->loan_count != 0) {
-
-			/*
-			 * avoid unneeded loan break if possible.
-			 */
-
-			if ((access_type & VM_PROT_WRITE) == 0)
-				prot &= ~VM_PROT_WRITE;
-
-			if (prot & VM_PROT_WRITE) {
-				struct vm_page *newpg;
-
-				newpg = uvm_loanbreak(pg);
-				if (newpg == NULL) {
-					uvm_page_unbusy(&pg, 1);
-					mutex_exit(&uobj->vmobjlock);
-					uvm_wait("ubc_loanbrk");
-					continue; /* will re-fault */
-				}
-				pg = newpg;
-			}
-		}
-
-		/*
-		 * note that a page whose backing store is partially allocated
-		 * is marked as PG_RDONLY.
-		 */
-
-		rdonly = ((access_type & VM_PROT_WRITE) == 0 &&
-		    (pg->flags & PG_RDONLY) != 0) ||
-		    UVM_OBJ_NEEDS_WRITEFAULT(uobj);
-		KASSERT((pg->flags & PG_RDONLY) == 0 ||
-		    (access_type & VM_PROT_WRITE) == 0 ||
-		    pg->offset < umap->writeoff ||
-		    pg->offset + PAGE_SIZE > umap->writeoff + umap->writelen);
-		mask = rdonly ? ~VM_PROT_WRITE : VM_PROT_ALL;
-		error = pmap_enter(ufi->orig_map->pmap, va, VM_PAGE_TO_PHYS(pg),
-		    prot & mask, PMAP_CANFAIL | (access_type & mask));
-		mutex_enter(&uvm_pageqlock);
-		uvm_pageactivate(pg);
-		mutex_exit(&uvm_pageqlock);
-		pg->flags &= ~(PG_BUSY|PG_WANTED);
-		UVM_PAGE_OWN(pg, NULL);
-		mutex_exit(&uobj->vmobjlock);
-		if (error) {
-			UVMHIST_LOG(ubchist, "pmap_enter fail %d",
-			    error, 0, 0, 0);
-			uvm_wait("ubc_pmfail");
-			/* will refault */
-		}
+		ubc_fault_page(ufi, umap, pg, prot, access_type, va);
 	}
 	pmap_update(ufi->orig_map->pmap);
 	return 0;

Reply via email to