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;
}
/*