Module Name:    src
Committed By:   yamt
Date:           Wed Jan 18 02:09:06 UTC 2012

Modified Files:
        src/sys/miscfs/genfs [yamt-pagecache]: genfs_io.c
        src/sys/uvm [yamt-pagecache]: uvm_loan.c uvm_page_array.c
            uvm_page_status.c uvm_vnode.c

Log Message:
- bug fixes
- minor optimizations
- assertions
- comments


To generate a diff of this commit:
cvs rdiff -u -r1.53.2.7 -r1.53.2.8 src/sys/miscfs/genfs/genfs_io.c
cvs rdiff -u -r1.81.2.11 -r1.81.2.12 src/sys/uvm/uvm_loan.c
cvs rdiff -u -r1.1.2.3 -r1.1.2.4 src/sys/uvm/uvm_page_array.c
cvs rdiff -u -r1.1.2.5 -r1.1.2.6 src/sys/uvm/uvm_page_status.c
cvs rdiff -u -r1.97.2.3 -r1.97.2.4 src/sys/uvm/uvm_vnode.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/miscfs/genfs/genfs_io.c
diff -u src/sys/miscfs/genfs/genfs_io.c:1.53.2.7 src/sys/miscfs/genfs/genfs_io.c:1.53.2.8
--- src/sys/miscfs/genfs/genfs_io.c:1.53.2.7	Sat Jan 14 04:44:45 2012
+++ src/sys/miscfs/genfs/genfs_io.c	Wed Jan 18 02:09:05 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: genfs_io.c,v 1.53.2.7 2012/01/14 04:44:45 yamt Exp $	*/
+/*	$NetBSD: genfs_io.c,v 1.53.2.8 2012/01/18 02:09:05 yamt Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.53.2.7 2012/01/14 04:44:45 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: genfs_io.c,v 1.53.2.8 2012/01/18 02:09:05 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -375,10 +375,11 @@ startover:
 			 */
 			pg->flags &= ~(PG_RDONLY|PG_HOLE);
 			/*
-			 * mark the page dirty.
+			 * mark the page DIRTY.
 			 * otherwise another thread can do putpages and pull
 			 * our vnode from syncer's queue before our caller does
-			 * ubc_release.
+			 * ubc_release.  note that putpages won't see CLEAN
+			 * pages even if they are BUSY.
 			 */
 			uvm_pagemarkdirty(pg, UVM_PAGE_STATUS_DIRTY);
 		}
@@ -852,7 +853,7 @@ genfs_do_putpages(struct vnode *vp, off_
 {
 	struct uvm_object * const uobj = &vp->v_uobj;
 	kmutex_t * const slock = uobj->vmobjlock;
-	off_t off;
+	off_t nextoff;
 	/* Even for strange MAXPHYS, the shift rounds down to a page */
 #define maxpages (MAXPHYS >> PAGE_SHIFT)
 	int i, error;
@@ -865,7 +866,7 @@ genfs_do_putpages(struct vnode *vp, off_
 	bool pagedaemon = curlwp == uvm.pagedaemon_lwp;
 	struct lwp * const l = curlwp ? curlwp : &lwp0;
 	int flags;
-	bool modified;		/* if we write out any pages */
+	bool written;		/* if we write out any pages */
 	bool need_wapbl;
 	bool has_trans;
 	bool tryclean;		/* try to pull off from the syncer's list */
@@ -886,7 +887,7 @@ genfs_do_putpages(struct vnode *vp, off_
 	    (origflags & PGO_JOURNALLOCKED) == 0);
 
 retry:
-	modified = false;
+	written = false;
 	flags = origflags;
 	KASSERT((vp->v_iflag & VI_ONWORKLST) != 0 ||
 	    (vp->v_iflag & VI_WRMAPDIRTY) == 0);
@@ -938,7 +939,7 @@ retry:
 
 	error = 0;
 	wasclean = (vp->v_numoutput == 0);
-	off = startoff;
+	nextoff = startoff;
 	if (endoff == 0 || flags & PGO_ALLPAGES) {
 		endoff = trunc_page(LLONG_MAX);
 	}
@@ -967,7 +968,7 @@ retry:
 	for (;;) {
 		bool protected;
 
-		pg = uvm_page_array_fill_and_peek(&a, uobj, off, 0,
+		pg = uvm_page_array_fill_and_peek(&a, uobj, nextoff, 0,
 		    dirtyonly ? UVM_PAGE_ARRAY_FILL_DIRTYONLY : 0);
 		if (pg == NULL) {
 			break;
@@ -981,7 +982,7 @@ retry:
 		KASSERT((pg->flags & (PG_RELEASED|PG_PAGEOUT)) == 0 ||
 		    (pg->flags & (PG_BUSY)) != 0);
 		KASSERT(pg->offset >= startoff);
-		KASSERT(pg->offset >= off);
+		KASSERT(pg->offset >= nextoff);
 		KASSERT(!dirtyonly ||
 		    uvm_pagegetdirty(pg) != UVM_PAGE_STATUS_CLEAN);
 		if (pg->offset >= endoff) {
@@ -990,7 +991,7 @@ retry:
 		if (pg->flags & (PG_RELEASED|PG_PAGEOUT)) {
 			KASSERT((pg->flags & PG_BUSY) != 0);
 			wasclean = false;
-			off = pg->offset + PAGE_SIZE;
+			nextoff = pg->offset + PAGE_SIZE;
 			uvm_page_array_advance(&a);
 			continue;
 		}
@@ -1018,7 +1019,7 @@ retry:
 				 */
 				break;
 			}
-			off = pg->offset; /* visit this page again */
+			nextoff = pg->offset; /* visit this page again */
 			if ((pg->flags & PG_BUSY) != 0) {
 				pg->flags |= PG_WANTED;
 				UVM_UNLOCK_AND_WAIT(pg, slock, 0, "genput", 0);
@@ -1036,7 +1037,7 @@ retry:
 			continue;
 		}
 
-		off = pg->offset + PAGE_SIZE;
+		nextoff = pg->offset + PAGE_SIZE;
 		uvm_page_array_advance(&a);
 
 		/*
@@ -1097,13 +1098,14 @@ retry:
 			pg->flags |= PG_BUSY;
 			UVM_PAGE_OWN(pg, "genfs_putpages");
 
+			fpflags = UFP_NOWAIT|UFP_NOALLOC|UFP_DIRTYONLY;
+
 			/*
 			 * XXX PG_PAGER1 incompatibility check.
 			 * this is a kludge for nfs.
 			 * probably it's better to make PG_NEEDCOMMIT a first
 			 * level citizen for uvm/genfs.
 			 */
-			fpflags = UFP_NOWAIT|UFP_NOALLOC|UFP_DIRTYONLY;
 			if ((pg->flags & PG_PAGER1) != 0) {
 				fpflags |= UFP_ONLYPAGER1;
 			} else {
@@ -1112,20 +1114,31 @@ retry:
 
 			/*
 			 * first look backward.
+			 *
+			 * because we always scan pages in the ascending order,
+			 * backward scan can be useful only for the first page
+			 * in the range.
 			 */
-			npages = MIN(maxpages >> 1, off >> PAGE_SHIFT);
-			nback = npages;
-			uvn_findpages(uobj, off - PAGE_SIZE, &nback, &pgs[0],
-			    NULL, fpflags | UFP_BACKWARD);
-			if (nback) {
-				memmove(&pgs[0], &pgs[npages - nback],
-				    nback * sizeof(pgs[0]));
-				if (npages - nback < nback)
-					memset(&pgs[nback], 0,
-					    (npages - nback) * sizeof(pgs[0]));
-				else
-					memset(&pgs[npages - nback], 0,
+			if (startoff == pg->offset) {
+				npages = MIN(maxpages >> 1,
+				    pg->offset >> PAGE_SHIFT);
+				nback = npages;
+				uvn_findpages(uobj, pg->offset - PAGE_SIZE,
+				    &nback, &pgs[0], NULL,
+				    fpflags | UFP_BACKWARD);
+				if (nback) {
+					memmove(&pgs[0], &pgs[npages - nback],
 					    nback * sizeof(pgs[0]));
+					if (npages - nback < nback)
+						memset(&pgs[nback], 0,
+						    (npages - nback) *
+						    sizeof(pgs[0]));
+					else
+						memset(&pgs[npages - nback], 0,
+						    nback * sizeof(pgs[0]));
+				}
+			} else {
+				nback = 0;
 			}
 
 			/*
@@ -1186,7 +1199,8 @@ retry:
 					KASSERT(npages == 1);
 					KASSERT(!needs_clean);
 					KASSERT(pg == tpg);
-					KASSERT(off == tpg->offset + PAGE_SIZE);
+					KASSERT(nextoff ==
+					    tpg->offset + PAGE_SIZE);
 					uvm_pagefree(tpg);
 					if (pagedaemon)
 						uvmexp.pdfreed++;
@@ -1197,21 +1211,22 @@ retry:
 			mutex_exit(&uvm_pageqlock);
 		}
 		if (needs_clean) {
-			KASSERT(off == pg->offset + PAGE_SIZE);
-			off = pg->offset + ((npages - nback) << PAGE_SHIFT);
-			KASSERT(pgs[nback] == pg);
-			KASSERT(off == pgs[npages - 1]->offset + PAGE_SIZE);
 			mutex_exit(slock);
+			KASSERT(nextoff == pg->offset + PAGE_SIZE);
+			nextoff = pg->offset + ((npages - nback) << PAGE_SHIFT);
+			KASSERT(pgs[nback] == pg);
+			KASSERT(nextoff == pgs[npages - 1]->offset + PAGE_SIZE);
 
 			/*
 			 * start the i/o.
-			 *
+			 */
+			error = GOP_WRITE(vp, pgs, npages, flags);
+			written = true;
+			/*
 			 * as we dropped the object lock, our cached pages can
 			 * be stale.
 			 */
-			modified = true;
 			uvm_page_array_clear(&a);
-			error = GOP_WRITE(vp, pgs, npages, flags);
 			mutex_enter(slock);
 			if (error) {
 				break;
@@ -1230,7 +1245,7 @@ retry:
 	 * might not involve any page faults.
 	 */
 
-	if (modified && (vp->v_iflag & VI_WRMAPDIRTY) != 0 &&
+	if (written && (vp->v_iflag & VI_WRMAPDIRTY) != 0 &&
 	    (vp->v_type != VBLK ||
 	    (vp->v_mount->mnt_flag & MNT_NODEVMTIME) == 0)) {
 		GOP_MARKUPDATE(vp, GOP_UPDATE_MODIFIED);

Index: src/sys/uvm/uvm_loan.c
diff -u src/sys/uvm/uvm_loan.c:1.81.2.11 src/sys/uvm/uvm_loan.c:1.81.2.12
--- src/sys/uvm/uvm_loan.c:1.81.2.11	Wed Jan 11 00:09:51 2012
+++ src/sys/uvm/uvm_loan.c	Wed Jan 18 02:09:06 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_loan.c,v 1.81.2.11 2012/01/11 00:09:51 yamt Exp $	*/
+/*	$NetBSD: uvm_loan.c,v 1.81.2.12 2012/01/18 02:09:06 yamt Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_loan.c,v 1.81.2.11 2012/01/11 00:09:51 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_loan.c,v 1.81.2.12 2012/01/18 02:09:06 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1386,7 +1386,7 @@ uvm_loanobj_read(struct vm_map *map, vad
 	unsigned int i, refs, aoff, pgoff;
 	unsigned int loaned; /* # of newly created O->A loan */
 	int error;
-	UVMHIST_FUNC("uvm_vnp_loanread"); UVMHIST_CALLED(ubchist);
+	UVMHIST_FUNC("uvm_loanobj_read"); UVMHIST_CALLED(ubchist);
 
 	UVMHIST_LOG(ubchist, "map %p va 0x%x npages %d", map, va, npages, 0);
 	UVMHIST_LOG(ubchist, "uobj %p off 0x%x", uobj, off, 0, 0);

Index: src/sys/uvm/uvm_page_array.c
diff -u src/sys/uvm/uvm_page_array.c:1.1.2.3 src/sys/uvm/uvm_page_array.c:1.1.2.4
--- src/sys/uvm/uvm_page_array.c:1.1.2.3	Sat Nov 26 15:19:06 2011
+++ src/sys/uvm/uvm_page_array.c	Wed Jan 18 02:09:06 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_page_array.c,v 1.1.2.3 2011/11/26 15:19:06 yamt Exp $	*/
+/*	$NetBSD: uvm_page_array.c,v 1.1.2.4 2012/01/18 02:09:06 yamt Exp $	*/
 
 /*-
  * Copyright (c)2011 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_page_array.c,v 1.1.2.3 2011/11/26 15:19:06 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_page_array.c,v 1.1.2.4 2012/01/18 02:09:06 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -138,7 +138,9 @@ uvm_page_array_fill(struct uvm_page_arra
 	if (nwant != 0 && nwant < maxpages) {
 		maxpages = nwant;
 	}
+#if 0 /* called from DDB for "show obj/f" without lock */
 	KASSERT(mutex_owned(uobj->vmobjlock));
+#endif
 	KASSERT(uvm_page_array_peek(ar) == NULL);
 	if ((flags & UVM_PAGE_ARRAY_FILL_DIRTYONLY) != 0) {
 		npages =

Index: src/sys/uvm/uvm_page_status.c
diff -u src/sys/uvm/uvm_page_status.c:1.1.2.5 src/sys/uvm/uvm_page_status.c:1.1.2.6
--- src/sys/uvm/uvm_page_status.c:1.1.2.5	Sun Nov 20 10:52:35 2011
+++ src/sys/uvm/uvm_page_status.c	Wed Jan 18 02:09:06 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_page_status.c,v 1.1.2.5 2011/11/20 10:52:35 yamt Exp $	*/
+/*	$NetBSD: uvm_page_status.c,v 1.1.2.6 2012/01/18 02:09:06 yamt Exp $	*/
 
 /*-
  * Copyright (c)2011 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_page_status.c,v 1.1.2.5 2011/11/20 10:52:35 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_page_status.c,v 1.1.2.6 2012/01/18 02:09:06 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -173,6 +173,7 @@ uvm_pagecheckdirty(struct vm_page *pg, b
 				pmap_clear_modify(pg);
 			}
 		} else {
+			KASSERT(oldstatus == UVM_PAGE_STATUS_UNKNOWN);
 			modified = pmap_clear_modify(pg);
 		}
 		uvm_pagemarkdirty(pg, newstatus);

Index: src/sys/uvm/uvm_vnode.c
diff -u src/sys/uvm/uvm_vnode.c:1.97.2.3 src/sys/uvm/uvm_vnode.c:1.97.2.4
--- src/sys/uvm/uvm_vnode.c:1.97.2.3	Tue Dec 20 13:46:17 2011
+++ src/sys/uvm/uvm_vnode.c	Wed Jan 18 02:09:06 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_vnode.c,v 1.97.2.3 2011/12/20 13:46:17 yamt Exp $	*/
+/*	$NetBSD: uvm_vnode.c,v 1.97.2.4 2012/01/18 02:09:06 yamt Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -45,7 +45,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.97.2.3 2011/12/20 13:46:17 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_vnode.c,v 1.97.2.4 2012/01/18 02:09:06 yamt Exp $");
 
 #include "opt_uvmhist.h"
 
@@ -210,7 +210,7 @@ uvn_findpages(struct uvm_object *uobj, v
 	if (flags & UFP_BACKWARD) {
 		for (i = npages - 1; i >= 0; i--, offset -= PAGE_SIZE) {
 			rv = uvn_findpage(uobj, offset, &pgs[i], flags, a,
-			    npages - i);
+			    i + 1);
 			if (rv == 0) {
 				if (flags & UFP_DIRTYONLY)
 					break;
@@ -242,9 +242,8 @@ uvn_findpage(struct uvm_object *uobj, vo
     unsigned int flags, struct uvm_page_array *a, unsigned int nleft)
 {
 	struct vm_page *pg;
-	bool dirty;
 	const unsigned int fillflags =
-	    ((flags & UFP_BACKWARD) ? UVM_PAGE_ARRAY_FILL_BACKWARD : 0) ||
+	    ((flags & UFP_BACKWARD) ? UVM_PAGE_ARRAY_FILL_BACKWARD : 0) |
 	    ((flags & UFP_DIRTYONLY) ?
 	    (UVM_PAGE_ARRAY_FILL_DIRTYONLY|UVM_PAGE_ARRAY_FILL_DENSE) : 0);
 	UVMHIST_FUNC("uvn_findpage"); UVMHIST_CALLED(ubchist);
@@ -254,14 +253,22 @@ uvn_findpage(struct uvm_object *uobj, vo
 
 	if (*pgp != NULL) {
 		UVMHIST_LOG(ubchist, "dontcare", 0,0,0,0);
-		goto skip;
+		goto skip_offset;
 	}
 	for (;;) {
-		/* look for an existing page */
+		/*
+		 * look for an existing page.
+		 *
+		 * XXX fragile API
+		 * note that the array can be the one supplied by the caller of
+		 * uvm_findpages.  in that case, fillflags used by the caller
+		 * might not match strictly with ours.
+		 * in particular, the caller might have filled the array
+		 * without DIRTYONLY or DENSE but passed us UFP_DIRTYONLY.
+		 */
 		pg = uvm_page_array_fill_and_peek(a, uobj, offset, nleft,
 		    fillflags);
 		if (pg != NULL && pg->offset != offset) {
-			KASSERT((fillflags & UVM_PAGE_ARRAY_FILL_DENSE) == 0);
 			KASSERT(
 			    ((fillflags & UVM_PAGE_ARRAY_FILL_BACKWARD) != 0)
 			    == (pg->offset < offset));
@@ -334,7 +341,8 @@ uvn_findpage(struct uvm_object *uobj, vo
 
 		/* stop on clean pages if requested */
 		if (flags & UFP_DIRTYONLY) {
-			dirty = uvm_pagecheckdirty(pg, false);
+			const bool dirty = uvm_pagecheckdirty(pg, false);
+
 			if (!dirty) {
 				UVMHIST_LOG(ubchist, "dirtonly", 0,0,0,0);
 				return 0;
@@ -352,7 +360,10 @@ uvn_findpage(struct uvm_object *uobj, vo
 	*pgp = pg;
 	return 1;
 
-skip:
+skip_offset:
+	/*
+	 * skip this offset
+	 */
 	pg = uvm_page_array_peek(a);
 	if (pg != NULL) {
 		if (pg->offset == offset) {
@@ -362,6 +373,14 @@ skip:
 		}
 	}
 	return 0;
+
+skip:
+	/*
+	 * skip this page
+	 */
+	KASSERT(pg != NULL);
+	uvm_page_array_advance(a);
+	return 0;
 }
 
 /*

Reply via email to