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