Module Name: src Committed By: christos Date: Sat May 24 16:34:04 UTC 2014
Modified Files: src/external/cddl/osnet/dist/uts/common/fs/zfs: zfs_vfsops.c src/share/man/man9: vfssubr.9 src/sys/fs/msdosfs: msdosfs_vfsops.c src/sys/fs/puffs: puffs_vfsops.c src/sys/fs/smbfs: smbfs_vfsops.c src/sys/kern: vfs_mount.c vfs_subr.c src/sys/nfs: nfs_subs.c nfs_vfsops.c src/sys/sys: mount.h param.h src/sys/ufs/ext2fs: ext2fs_vfsops.c src/sys/ufs/ffs: ffs_snapshot.c ffs_vfsops.c src/sys/ufs/lfs: ulfs_quota1.c src/sys/ufs/ufs: ufs_quota1.c Log Message: Introduce a selector function to the vfs vnode iterator so that we don't need to vget() vnodes that we are not interested at, and optimize locking a bit. Iterator changes reviewed by Hannken (thanks), the rest of the bugs are mine. To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.13 \ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c cvs rdiff -u -r1.23 -r1.24 src/share/man/man9/vfssubr.9 cvs rdiff -u -r1.107 -r1.108 src/sys/fs/msdosfs/msdosfs_vfsops.c cvs rdiff -u -r1.110 -r1.111 src/sys/fs/puffs/puffs_vfsops.c cvs rdiff -u -r1.100 -r1.101 src/sys/fs/smbfs/smbfs_vfsops.c cvs rdiff -u -r1.28 -r1.29 src/sys/kern/vfs_mount.c cvs rdiff -u -r1.443 -r1.444 src/sys/kern/vfs_subr.c cvs rdiff -u -r1.225 -r1.226 src/sys/nfs/nfs_subs.c cvs rdiff -u -r1.227 -r1.228 src/sys/nfs/nfs_vfsops.c cvs rdiff -u -r1.213 -r1.214 src/sys/sys/mount.h cvs rdiff -u -r1.452 -r1.453 src/sys/sys/param.h cvs rdiff -u -r1.181 -r1.182 src/sys/ufs/ext2fs/ext2fs_vfsops.c cvs rdiff -u -r1.133 -r1.134 src/sys/ufs/ffs/ffs_snapshot.c cvs rdiff -u -r1.298 -r1.299 src/sys/ufs/ffs/ffs_vfsops.c cvs rdiff -u -r1.7 -r1.8 src/sys/ufs/lfs/ulfs_quota1.c cvs rdiff -u -r1.19 -r1.20 src/sys/ufs/ufs/ufs_quota1.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c:1.12 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c:1.13 --- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c:1.12 Wed Apr 16 14:55:18 2014 +++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c Sat May 24 12:34:03 2014 @@ -147,6 +147,20 @@ static mntopts_t zfs_mntopts = { mntopts }; +static bool +zfs_sync_selector(void *cl, struct vnode *vp) +{ + znode_t *zp; + + /* + * Skip the vnode/inode if inaccessible, or if the + * atime is clean. + */ + zp = VTOZ(vp); + return zp != NULL && vp->v_type != VNON && zp->z_atime_dirty != 0 + && !zp->z_unlinked; +} + /*ARGSUSED*/ int zfs_sync(vfs_t *vfsp, int flag, cred_t *cr) @@ -174,22 +188,14 @@ zfs_sync(vfs_t *vfsp, int flag, cred_t * * BSD VFS, so we do it in batch here. */ vfs_vnode_iterator_init(vfsp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, zfs_sync_selector, NULL))) + { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); continue; } - /* - * Skip the vnode/inode if inaccessible, or if the - * atime is clean. - */ zp = VTOZ(vp); - if (zp == NULL || vp->v_type == VNON || - zp->z_atime_dirty == 0 || zp->z_unlinked) { - vput(vp); - continue; - } tx = dmu_tx_create(zfsvfs->z_os); dmu_tx_hold_bonus(tx, zp->z_id); error = dmu_tx_assign(tx, TXG_WAIT); Index: src/share/man/man9/vfssubr.9 diff -u src/share/man/man9/vfssubr.9:1.23 src/share/man/man9/vfssubr.9:1.24 --- src/share/man/man9/vfssubr.9:1.23 Tue Mar 18 06:21:47 2014 +++ src/share/man/man9/vfssubr.9 Sat May 24 12:34:03 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: vfssubr.9,v 1.23 2014/03/18 10:21:47 hannken Exp $ +.\" $NetBSD: vfssubr.9,v 1.24 2014/05/24 16:34:03 christos Exp $ .\" .\" Copyright (c) 2003, 2005, 2006 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd March 18, 2014 +.Dd May 24, 2014 .Dt VFSSUBR 9 .Os .Sh NAME @@ -100,11 +100,11 @@ .Ft void .Fn vfs_resume "struct mount *mp" .Ft void -.Fn vfs_vnode_iterator_init "struct mount *mp" " struct vnode_iterator **vip" +.Fn vfs_vnode_iterator_init "struct mount *mp" "struct vnode_iterator **vip" .Ft void .Fn vfs_vnode_iterator_destroy "struct vnode_iterator *vi" -.Ft bool -.Fn vfs_vnode_iterator_next "struct vnode_iterator *vi" " struct vnode **vpp" +.Ft struct vnode * +.Fn vfs_vnode_iterator_next "struct vnode_iterator *vi" "bool (*selector)(void *context, struct vnode *vpp)" "void *context" .Sh DESCRIPTION The high-level functions described in this page are the interface to the kernel file system interface (VFS). @@ -243,20 +243,26 @@ over all vnodes attached to mount point .It Fn vfs_vnode_iterator_destroy "vi" Free all resources associated with an iterator .Fa vi . -.It Fn vfs_vnode_iterator_next "vi" "vpp" +.It Fn vfs_vnode_iterator_next "vi" "selector" "context" Return the next vnode from iterator .Fa vi . If the operation is successful the vnode has a reference added to it -and it is returned in -.Fa *vpp -and the function returns -.Dv true . -If the iterator is exhausted, -.Fa *vpp -is -.Dv NULL -and the function returns -.Dv false . +and it is returned +If the iterator is exhausted +the function returns +.Dv NULL . +If an optional +.Fa selector +function is provided, then this function is called with the +.Fa context +provided and the candidate vnode to be returned. +If the +.Fa selector +returns +.Dv false , +then the vnode is skipped; if it returns +.Dv true , +the vnode is referenced and then returned. .El .Sh CODE REFERENCES The vfs interface functions are implemented within the files Index: src/sys/fs/msdosfs/msdosfs_vfsops.c diff -u src/sys/fs/msdosfs/msdosfs_vfsops.c:1.107 src/sys/fs/msdosfs/msdosfs_vfsops.c:1.108 --- src/sys/fs/msdosfs/msdosfs_vfsops.c:1.107 Wed Apr 16 14:55:18 2014 +++ src/sys/fs/msdosfs/msdosfs_vfsops.c Sat May 24 12:34:03 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: msdosfs_vfsops.c,v 1.107 2014/04/16 18:55:18 maxv Exp $ */ +/* $NetBSD: msdosfs_vfsops.c,v 1.108 2014/05/24 16:34:03 christos Exp $ */ /*- * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.107 2014/04/16 18:55:18 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.108 2014/05/24 16:34:03 christos Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -943,14 +943,34 @@ msdosfs_statvfs(struct mount *mp, struct return (0); } +struct msdosfs_sync_ctx { + int waitfor; +}; + +static bool +msdosfs_sync_selector(void *cl, struct vnode *vp) +{ + struct msdosfs_sync_ctx *c = cl; + struct denode *dep; + + dep = VTODE(vp); + if (c->waitfor == MNT_LAZY || vp->v_type == VNON || + dep == NULL || (((dep->de_flag & + (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0) && + (LIST_EMPTY(&vp->v_dirtyblkhd) && + UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) + return false; + return true; +} + int msdosfs_sync(struct mount *mp, int waitfor, kauth_cred_t cred) { struct vnode *vp; struct vnode_iterator *marker; - struct denode *dep; struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); int error, allerror = 0; + struct msdosfs_sync_ctx ctx; /* * If we ever switch to not updating all of the FATs all the time, @@ -968,21 +988,15 @@ msdosfs_sync(struct mount *mp, int waitf * Write back each (modified) denode. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + ctx.waitfor = waitfor; + while ((vp = vfs_vnode_iterator_next(marker, msdosfs_sync_selector, + &ctx))) + { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); continue; } - dep = VTODE(vp); - if (waitfor == MNT_LAZY || vp->v_type == VNON || - dep == NULL || (((dep->de_flag & - (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0) && - (LIST_EMPTY(&vp->v_dirtyblkhd) && - UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) { - vput(vp); - continue; - } if ((error = VOP_FSYNC(vp, cred, waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0)) != 0) allerror = error; Index: src/sys/fs/puffs/puffs_vfsops.c diff -u src/sys/fs/puffs/puffs_vfsops.c:1.110 src/sys/fs/puffs/puffs_vfsops.c:1.111 --- src/sys/fs/puffs/puffs_vfsops.c:1.110 Wed Apr 16 14:55:18 2014 +++ src/sys/fs/puffs/puffs_vfsops.c Sat May 24 12:34:03 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_vfsops.c,v 1.110 2014/04/16 18:55:18 maxv Exp $ */ +/* $NetBSD: puffs_vfsops.c,v 1.111 2014/05/24 16:34:03 christos Exp $ */ /* * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.110 2014/04/16 18:55:18 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.111 2014/05/24 16:34:03 christos Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -510,6 +510,18 @@ puffs_vfsop_statvfs(struct mount *mp, st return error; } +static bool +pageflush_selector(void *cl, struct vnode *vp) +{ + bool rv; + + mutex_enter(vp->v_interlock); + rv = vp->v_type == VREG && !UVM_OBJ_IS_CLEAN(&vp->v_uobj); + mutex_exit(vp->v_interlock); + + return rv; +} + static int pageflush(struct mount *mp, kauth_cred_t cred, int waitfor) { @@ -528,7 +540,9 @@ pageflush(struct mount *mp, kauth_cred_t * all the nodes it knows to exist. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, pageflush_selector, + NULL))) + { /* * Here we try to get a reference to the vnode and to * lock it. This is mostly cargo-culted, but I will @@ -550,11 +564,6 @@ pageflush(struct mount *mp, kauth_cred_t continue; } pn = VPTOPP(vp); - if (vp->v_type != VREG || UVM_OBJ_IS_CLEAN(&vp->v_uobj)) { - vput(vp); - continue; - } - /* hmm.. is the FAF thing entirely sensible? */ if (waitfor == MNT_LAZY) { mutex_enter(vp->v_interlock); Index: src/sys/fs/smbfs/smbfs_vfsops.c diff -u src/sys/fs/smbfs/smbfs_vfsops.c:1.100 src/sys/fs/smbfs/smbfs_vfsops.c:1.101 --- src/sys/fs/smbfs/smbfs_vfsops.c:1.100 Wed Apr 16 14:55:18 2014 +++ src/sys/fs/smbfs/smbfs_vfsops.c Sat May 24 12:34:03 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: smbfs_vfsops.c,v 1.100 2014/04/16 18:55:18 maxv Exp $ */ +/* $NetBSD: smbfs_vfsops.c,v 1.101 2014/05/24 16:34:03 christos Exp $ */ /* * Copyright (c) 2000-2001, Boris Popov @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: smbfs_vfsops.c,v 1.100 2014/04/16 18:55:18 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: smbfs_vfsops.c,v 1.101 2014/05/24 16:34:03 christos Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -400,6 +400,23 @@ smbfs_statvfs(struct mount *mp, struct s return 0; } +static bool +smbfs_sync_selector(void *cl, struct vnode *vp) +{ + struct smbnode *np; + + np = VTOSMB(vp); + if (np == NULL) + return false; + + if ((vp->v_type == VNON || (np->n_flag & NMODIFIED) == 0) && + LIST_EMPTY(&vp->v_dirtyblkhd) && + vp->v_uobj.uo_npages == 0) + return false; + + return true; +} + /* * Flush out the buffer cache */ @@ -408,27 +425,17 @@ smbfs_sync(struct mount *mp, int waitfor { struct vnode *vp; struct vnode_iterator *marker; - struct smbnode *np; int error, allerror = 0; vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, smbfs_sync_selector, + NULL))) + { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); continue; } - np = VTOSMB(vp); - if (np == NULL) { - vput(vp); - continue; - } - if ((vp->v_type == VNON || (np->n_flag & NMODIFIED) == 0) && - LIST_EMPTY(&vp->v_dirtyblkhd) && - vp->v_uobj.uo_npages == 0) { - vput(vp); - continue; - } error = VOP_FSYNC(vp, cred, waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0); if (error) Index: src/sys/kern/vfs_mount.c diff -u src/sys/kern/vfs_mount.c:1.28 src/sys/kern/vfs_mount.c:1.29 --- src/sys/kern/vfs_mount.c:1.28 Tue Mar 18 06:21:47 2014 +++ src/sys/kern/vfs_mount.c Sat May 24 12:34:04 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_mount.c,v 1.28 2014/03/18 10:21:47 hannken Exp $ */ +/* $NetBSD: vfs_mount.c,v 1.29 2014/05/24 16:34:04 christos Exp $ */ /*- * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.28 2014/03/18 10:21:47 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.29 2014/05/24 16:34:04 christos Exp $"); #define _VFS_VNODE_PRIVATE @@ -371,8 +371,9 @@ vfs_vnode_iterator_destroy(struct vnode_ vnfree(mvp); } -bool -vfs_vnode_iterator_next(struct vnode_iterator *vi, struct vnode **vpp) +struct vnode * +vfs_vnode_iterator_next(struct vnode_iterator *vi, + bool (*f)(void *, struct vnode *), void *cl) { struct vnode *mvp = &vi->vi_vnode; struct mount *mp = mvp->v_mount; @@ -386,22 +387,18 @@ vfs_vnode_iterator_next(struct vnode_ite vp = TAILQ_NEXT(mvp, v_mntvnodes); TAILQ_REMOVE(&mp->mnt_vnodelist, mvp, v_mntvnodes); mvp->v_usecount = 0; +again: if (vp == NULL) { mutex_exit(&mntvnode_lock); - *vpp = NULL; - return false; + return NULL; } - mutex_enter(vp->v_interlock); - while ((vp->v_iflag & VI_MARKER) != 0) { + while (ISSET(vp->v_iflag, VI_MARKER) || + ISSET(vp->v_iflag, VI_XLOCK) || + (f && !(*f)(cl, vp))) { mutex_exit(vp->v_interlock); vp = TAILQ_NEXT(vp, v_mntvnodes); - if (vp == NULL) { - mutex_exit(&mntvnode_lock); - *vpp = NULL; - return false; - } - mutex_enter(vp->v_interlock); + goto again; } TAILQ_INSERT_AFTER(&mp->mnt_vnodelist, vp, mvp, v_mntvnodes); @@ -411,8 +408,7 @@ vfs_vnode_iterator_next(struct vnode_ite KASSERT(error == 0 || error == ENOENT); } while (error != 0); - *vpp = vp; - return true; + return vp; } /* @@ -465,59 +461,64 @@ int busyprt = 0; /* print out busy vnode struct ctldebug debug1 = { "busyprt", &busyprt }; #endif -static vnode_t * -vflushnext(struct vnode_iterator *marker, int *when) +struct vflush_ctx { + const struct vnode *skipvp; + int flags; +}; + +static bool +vflush_selector(void *cl, struct vnode *vp) { - struct vnode *vp; + struct vflush_ctx *c = cl; + /* + * Skip over a selected vnode. + */ + if (vp == c->skipvp) + return false; + /* + * Skip over a vnodes marked VSYSTEM. + */ + if ((c->flags & SKIPSYSTEM) && (vp->v_vflag & VV_SYSTEM)) + return false; + + /* + * If WRITECLOSE is set, only flush out regular file + * vnodes open for writing. + */ + if ((c->flags & WRITECLOSE) && vp->v_type == VREG) { + if (vp->v_writecount == 0) + return false; + } + return true; +} +static vnode_t * +vflushnext(struct vnode_iterator *marker, void *ctx, int *when) +{ if (hardclock_ticks > *when) { yield(); *when = hardclock_ticks + hz / 10; } - if (vfs_vnode_iterator_next(marker, &vp)) - return vp; - return NULL; + return vfs_vnode_iterator_next(marker, vflush_selector, ctx); } + int vflush(struct mount *mp, vnode_t *skipvp, int flags) { vnode_t *vp; struct vnode_iterator *marker; int busy = 0, when = 0; + struct vflush_ctx ctx; /* First, flush out any vnode references from vrele_list. */ vrele_flush(); vfs_vnode_iterator_init(mp, &marker); - while ((vp = vflushnext(marker, &when)) != NULL) { - /* - * Skip over a selected vnode. - */ - if (vp == skipvp) { - vrele(vp); - continue; - } - /* - * Skip over a vnodes marked VSYSTEM. - */ - if ((flags & SKIPSYSTEM) && (vp->v_vflag & VV_SYSTEM)) { - vrele(vp); - continue; - } - /* - * If WRITECLOSE is set, only flush out regular file - * vnodes open for writing. - */ - if ((flags & WRITECLOSE) && vp->v_type == VREG) { - mutex_enter(vp->v_interlock); - if (vp->v_writecount == 0) { - mutex_exit(vp->v_interlock); - vrele(vp); - continue; - } - mutex_exit(vp->v_interlock); - } + + ctx.skipvp = skipvp; + ctx.flags = flags; + while ((vp = vflushnext(marker, &ctx, &when)) != NULL) { /* * First try to recycle the vnode. */ Index: src/sys/kern/vfs_subr.c diff -u src/sys/kern/vfs_subr.c:1.443 src/sys/kern/vfs_subr.c:1.444 --- src/sys/kern/vfs_subr.c:1.443 Mon Mar 17 05:28:37 2014 +++ src/sys/kern/vfs_subr.c Sat May 24 12:34:04 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_subr.c,v 1.443 2014/03/17 09:28:37 hannken Exp $ */ +/* $NetBSD: vfs_subr.c,v 1.444 2014/05/24 16:34:04 christos Exp $ */ /*- * Copyright (c) 1997, 1998, 2004, 2005, 2007, 2008 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.443 2014/03/17 09:28:37 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_subr.c,v 1.444 2014/05/24 16:34:04 christos Exp $"); #include "opt_ddb.h" #include "opt_compat_netbsd.h" @@ -637,7 +637,7 @@ sysctl_kern_vnode(SYSCTLFN_ARGS) continue; } vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { if (bp + VPTRSZ + VNODESZ > ewhere) { vrele(vp); vfs_vnode_iterator_destroy(marker); Index: src/sys/nfs/nfs_subs.c diff -u src/sys/nfs/nfs_subs.c:1.225 src/sys/nfs/nfs_subs.c:1.226 --- src/sys/nfs/nfs_subs.c:1.225 Mon Mar 17 05:35:24 2014 +++ src/sys/nfs/nfs_subs.c Sat May 24 12:34:04 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_subs.c,v 1.225 2014/03/17 09:35:24 hannken Exp $ */ +/* $NetBSD: nfs_subs.c,v 1.226 2014/05/24 16:34:04 christos Exp $ */ /* * Copyright (c) 1989, 1993 @@ -70,7 +70,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.225 2014/03/17 09:35:24 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.226 2014/05/24 16:34:04 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_nfs.h" @@ -1743,6 +1743,30 @@ netaddr_match(int family, union nethosta return (0); } +struct nfs_clearcommit_ctx { + struct mount *mp; +}; + +static bool +nfs_clearcommit_selector(void *cl, struct vnode *vp) +{ + struct nfs_clearcommit_ctx *c = cl; + struct nfsnode *np; + struct vm_page *pg; + + np = VTONFS(vp); + if (vp->v_type != VREG || vp->v_mount != c->mp || np == NULL) + return false; + np->n_pushlo = np->n_pushhi = np->n_pushedlo = + np->n_pushedhi = 0; + np->n_commitflags &= + ~(NFS_COMMIT_PUSH_VALID | NFS_COMMIT_PUSHED_VALID); + TAILQ_FOREACH(pg, &vp->v_uobj.memq, listq.queue) { + pg->flags &= ~PG_NEEDCOMMIT; + } + return false; +} + /* * The write verifier has changed (probably due to a server reboot), so all * PG_NEEDCOMMIT pages will have to be written again. Since they are marked @@ -1753,32 +1777,16 @@ netaddr_match(int family, union nethosta void nfs_clearcommit(struct mount *mp) { - struct vnode *vp; + struct vnode *vp __diagused; struct vnode_iterator *marker; - struct nfsnode *np; - struct vm_page *pg; struct nfsmount *nmp = VFSTONFS(mp); + struct nfs_clearcommit_ctx ctx; rw_enter(&nmp->nm_writeverflock, RW_WRITER); vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { - mutex_enter(vp->v_interlock); - np = VTONFS(vp); - if (vp->v_type != VREG || vp->v_mount != mp || np == NULL) { - mutex_exit(vp->v_interlock); - vrele(vp); - continue; - } - np->n_pushlo = np->n_pushhi = np->n_pushedlo = - np->n_pushedhi = 0; - np->n_commitflags &= - ~(NFS_COMMIT_PUSH_VALID | NFS_COMMIT_PUSHED_VALID); - TAILQ_FOREACH(pg, &vp->v_uobj.memq, listq.queue) { - pg->flags &= ~PG_NEEDCOMMIT; - } - mutex_exit(vp->v_interlock); - vrele(vp); - } + ctx.mp = mp; + vp = vfs_vnode_iterator_next(marker, nfs_clearcommit_selector, &ctx); + KASSERT(vp == NULL); vfs_vnode_iterator_destroy(marker); mutex_enter(&nmp->nm_lock); nmp->nm_iflag &= ~NFSMNT_STALEWRITEVERF; Index: src/sys/nfs/nfs_vfsops.c diff -u src/sys/nfs/nfs_vfsops.c:1.227 src/sys/nfs/nfs_vfsops.c:1.228 --- src/sys/nfs/nfs_vfsops.c:1.227 Wed Apr 16 14:55:17 2014 +++ src/sys/nfs/nfs_vfsops.c Sat May 24 12:34:04 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_vfsops.c,v 1.227 2014/04/16 18:55:17 maxv Exp $ */ +/* $NetBSD: nfs_vfsops.c,v 1.228 2014/05/24 16:34:04 christos Exp $ */ /* * Copyright (c) 1989, 1993, 1995 @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nfs_vfsops.c,v 1.227 2014/04/16 18:55:17 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nfs_vfsops.c,v 1.228 2014/05/24 16:34:04 christos Exp $"); #if defined(_KERNEL_OPT) #include "opt_nfs.h" @@ -937,6 +937,13 @@ nfs_root(struct mount *mp, struct vnode extern int syncprt; +static bool +nfs_sync_selector(void *cl, struct vnode *vp) +{ + + return !LIST_EMPTY(&vp->v_dirtyblkhd) || !UVM_OBJ_IS_CLEAN(&vp->v_uobj); +} + /* * Flush out the buffer cache */ @@ -952,17 +959,14 @@ nfs_sync(struct mount *mp, int waitfor, * Force stale buffer cache information to be flushed. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, nfs_sync_selector, + NULL))) + { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); continue; } - if (LIST_EMPTY(&vp->v_dirtyblkhd) && - UVM_OBJ_IS_CLEAN(&vp->v_uobj)) { - vput(vp); - continue; - } error = VOP_FSYNC(vp, cred, waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0); if (error) Index: src/sys/sys/mount.h diff -u src/sys/sys/mount.h:1.213 src/sys/sys/mount.h:1.214 --- src/sys/sys/mount.h:1.213 Thu May 8 04:21:53 2014 +++ src/sys/sys/mount.h Sat May 24 12:34:03 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: mount.h,v 1.213 2014/05/08 08:21:53 hannken Exp $ */ +/* $NetBSD: mount.h,v 1.214 2014/05/24 16:34:03 christos Exp $ */ /* * Copyright (c) 1989, 1991, 1993 @@ -442,7 +442,8 @@ int vfs_quotactl_quotaoff(struct mount * struct vnode_iterator; /* Opaque. */ void vfs_vnode_iterator_init(struct mount *, struct vnode_iterator **); void vfs_vnode_iterator_destroy(struct vnode_iterator *); -bool vfs_vnode_iterator_next(struct vnode_iterator *, struct vnode **); +struct vnode *vfs_vnode_iterator_next(struct vnode_iterator *, + bool (*)(void *, struct vnode *), void *); extern TAILQ_HEAD(mntlist, mount) mountlist; /* mounted filesystem list */ extern struct vfsops *vfssw[]; /* filesystem type table */ Index: src/sys/sys/param.h diff -u src/sys/sys/param.h:1.452 src/sys/sys/param.h:1.453 --- src/sys/sys/param.h:1.452 Sun May 18 10:46:16 2014 +++ src/sys/sys/param.h Sat May 24 12:34:03 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: param.h,v 1.452 2014/05/18 14:46:16 rmind Exp $ */ +/* $NetBSD: param.h,v 1.453 2014/05/24 16:34:03 christos Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1993 @@ -63,7 +63,7 @@ * 2.99.9 (299000900) */ -#define __NetBSD_Version__ 699004200 /* NetBSD 6.99.42 */ +#define __NetBSD_Version__ 699004300 /* NetBSD 6.99.43 */ #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \ (m) * 1000000) + (p) * 100) <= __NetBSD_Version__) Index: src/sys/ufs/ext2fs/ext2fs_vfsops.c diff -u src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.181 src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.182 --- src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.181 Thu May 8 04:21:53 2014 +++ src/sys/ufs/ext2fs/ext2fs_vfsops.c Sat May 24 12:34:04 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_vfsops.c,v 1.181 2014/05/08 08:21:53 hannken Exp $ */ +/* $NetBSD: ext2fs_vfsops.c,v 1.182 2014/05/24 16:34:04 christos Exp $ */ /* * Copyright (c) 1989, 1991, 1993, 1994 @@ -60,7 +60,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.181 2014/05/08 08:21:53 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.182 2014/05/24 16:34:04 christos Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -588,7 +588,7 @@ ext2fs_reload(struct mount *mp, kauth_cr } vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { /* * Step 4: invalidate all inactive vnodes. */ @@ -862,6 +862,26 @@ ext2fs_statvfs(struct mount *mp, struct return (0); } +static bool +ext2fs_sync_selector(void *cl, struct vnode *vp) +{ + struct inode *ip; + + ip = VTOI(vp); + /* + * Skip the vnode/inode if inaccessible. + */ + if (ip == NULL || vp->v_type == VNON) + return false; + + if (((ip->i_flag & + (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) == 0 && + LIST_EMPTY(&vp->v_dirtyblkhd) && + UVM_OBJ_IS_CLEAN(&vp->v_uobj))) + return false; + return true; +} + /* * Go through the disk queues to initiate sandbagged IO; * go through the inodes to write those that have been modified; @@ -873,7 +893,6 @@ int ext2fs_sync(struct mount *mp, int waitfor, kauth_cred_t cred) { struct vnode *vp; - struct inode *ip; struct ufsmount *ump = VFSTOUFS(mp); struct m_ext2fs *fs; struct vnode_iterator *marker; @@ -889,28 +908,14 @@ ext2fs_sync(struct mount *mp, int waitfo * Write back each (modified) inode. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, ext2fs_sync_selector, + NULL))) + { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); continue; } - ip = VTOI(vp); - /* - * Skip the vnode/inode if inaccessible. - */ - if (ip == NULL || vp->v_type == VNON) { - vput(vp); - continue; - } - - if (((ip->i_flag & - (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) == 0 && - LIST_EMPTY(&vp->v_dirtyblkhd) && - UVM_OBJ_IS_CLEAN(&vp->v_uobj))) { - vput(vp); - continue; - } if (vp->v_type == VREG && waitfor == MNT_LAZY) error = ext2fs_update(vp, NULL, NULL, 0); else Index: src/sys/ufs/ffs/ffs_snapshot.c diff -u src/sys/ufs/ffs/ffs_snapshot.c:1.133 src/sys/ufs/ffs/ffs_snapshot.c:1.134 --- src/sys/ufs/ffs/ffs_snapshot.c:1.133 Mon Mar 17 05:29:20 2014 +++ src/sys/ufs/ffs/ffs_snapshot.c Sat May 24 12:34:04 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_snapshot.c,v 1.133 2014/03/17 09:29:20 hannken Exp $ */ +/* $NetBSD: ffs_snapshot.c,v 1.134 2014/05/24 16:34:04 christos Exp $ */ /* * Copyright 2000 Marshall Kirk McKusick. All Rights Reserved. @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.133 2014/03/17 09:29:20 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.134 2014/05/24 16:34:04 christos Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -600,6 +600,42 @@ snapshot_copyfs(struct mount *mp, struct return 0; } +struct snapshot_expunge_ctx { + struct vnode *logvp; + struct lwp *l; + struct vnode *vp; + struct fs *copy_fs; +}; + +static bool +snapshot_expunge_selector(void *cl, struct vnode *xvp) +{ + struct vattr vat; + struct snapshot_expunge_ctx *c = cl; + struct inode *xp; + + xp = VTOI(xvp); + if (xvp->v_type == VNON || VTOI(xvp) == NULL || + (xp->i_flags & SF_SNAPSHOT)) + return false; +#ifdef DEBUG + if (snapdebug) + vprint("ffs_snapshot: busy vnode", xvp); +#endif + + if (xvp == c->logvp) + return true; + + if (VOP_GETATTR(xvp, &vat, c->l->l_cred) == 0 && + vat.va_nlink > 0) + return false; + + if (ffs_checkfreefile(c->copy_fs, c->vp, xp->i_number)) + return false; + + return true; +} + /* * We must check for active files that have been unlinked (e.g., with a zero * link count). We have to expunge all trace of these files from the snapshot @@ -616,9 +652,9 @@ snapshot_expunge(struct mount *mp, struc struct fs *fs = VFSTOUFS(mp)->um_fs; struct inode *xp; struct lwp *l = curlwp; - struct vattr vat; struct vnode *logvp = NULL, *xvp; struct vnode_iterator *marker; + struct snapshot_expunge_ctx ctx; *snaplist = NULL; /* @@ -638,31 +674,17 @@ snapshot_expunge(struct mount *mp, struc FSMAXSNAP + 1 /* superblock */ + 1 /* last block */ + 1 /* size */; vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &xvp)) { - if (xvp->v_type == VNON || VTOI(xvp) == NULL || - (VTOI(xvp)->i_flags & SF_SNAPSHOT)) { - vrele(xvp); - continue; - } -#ifdef DEBUG - if (snapdebug) - vprint("ffs_snapshot: busy vnode", xvp); -#endif - xp = VTOI(xvp); - if (xvp != logvp) { - if (VOP_GETATTR(xvp, &vat, l->l_cred) == 0 && - vat.va_nlink > 0) { - vrele(xvp); - continue; - } - if (ffs_checkfreefile(copy_fs, vp, xp->i_number)) { - vrele(xvp); - continue; - } - } + ctx.logvp = logvp; + ctx.l = l; + ctx.vp = vp; + ctx.copy_fs = copy_fs; + while ((xvp = vfs_vnode_iterator_next(marker, snapshot_expunge_selector, + &ctx))) + { /* * If there is a fragment, clear it here. */ + xp = VTOI(xvp); blkno = 0; loc = howmany(xp->i_size, fs->fs_bsize) - 1; if (loc < UFS_NDADDR) { Index: src/sys/ufs/ffs/ffs_vfsops.c diff -u src/sys/ufs/ffs/ffs_vfsops.c:1.298 src/sys/ufs/ffs/ffs_vfsops.c:1.299 --- src/sys/ufs/ffs/ffs_vfsops.c:1.298 Thu May 8 04:21:53 2014 +++ src/sys/ufs/ffs/ffs_vfsops.c Sat May 24 12:34:04 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_vfsops.c,v 1.298 2014/05/08 08:21:53 hannken Exp $ */ +/* $NetBSD: ffs_vfsops.c,v 1.299 2014/05/24 16:34:04 christos Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.298 2014/05/08 08:21:53 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.299 2014/05/24 16:34:04 christos Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -808,7 +808,7 @@ ffs_reload(struct mount *mp, kauth_cred_ } vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { /* * Step 4: invalidate all inactive vnodes. */ @@ -1594,6 +1594,51 @@ ffs_statvfs(struct mount *mp, struct sta return (0); } +struct ffs_sync_ctx { + int waitfor; + bool is_suspending; +}; + +static bool +ffs_sync_selector(void *cl, struct vnode *vp) +{ + struct ffs_sync_ctx *c = cl; + struct inode *ip; + + ip = VTOI(vp); + /* + * Skip the vnode/inode if inaccessible. + */ + if (ip == NULL || vp->v_type == VNON) + return false; + + /* + * We deliberately update inode times here. This will + * prevent a massive queue of updates accumulating, only + * to be handled by a call to unmount. + * + * XXX It would be better to have the syncer trickle these + * out. Adjustment needed to allow registering vnodes for + * sync when the vnode is clean, but the inode dirty. Or + * have ufs itself trickle out inode updates. + * + * If doing a lazy sync, we don't care about metadata or + * data updates, because they are handled by each vnode's + * synclist entry. In this case we are only interested in + * writing back modified inodes. + */ + if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | + IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) == 0 && + (c->waitfor == MNT_LAZY || (LIST_EMPTY(&vp->v_dirtyblkhd) && + UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) + return false; + + if (vp->v_type == VBLK && c->is_suspending) + return false; + + return true; +} + /* * Go through the disk queues to initiate sandbagged IO; * go through the inodes to write those that have been modified; @@ -1605,12 +1650,12 @@ int ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred) { struct vnode *vp; - struct inode *ip; struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs; struct vnode_iterator *marker; int error, allerror = 0; bool is_suspending; + struct ffs_sync_ctx ctx; fs = ump->um_fs; if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */ @@ -1624,47 +1669,16 @@ ffs_sync(struct mount *mp, int waitfor, * Write back each (modified) inode. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + + ctx.waitfor = waitfor; + ctx.is_suspending = is_suspending; + while ((vp = vfs_vnode_iterator_next(marker, ffs_sync_selector, &ctx))) + { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); continue; } - ip = VTOI(vp); - /* - * Skip the vnode/inode if inaccessible. - */ - if (ip == NULL || vp->v_type == VNON) { - vput(vp); - continue; - } - - /* - * We deliberately update inode times here. This will - * prevent a massive queue of updates accumulating, only - * to be handled by a call to unmount. - * - * XXX It would be better to have the syncer trickle these - * out. Adjustment needed to allow registering vnodes for - * sync when the vnode is clean, but the inode dirty. Or - * have ufs itself trickle out inode updates. - * - * If doing a lazy sync, we don't care about metadata or - * data updates, because they are handled by each vnode's - * synclist entry. In this case we are only interested in - * writing back modified inodes. - */ - if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE | - IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) == 0 && - (waitfor == MNT_LAZY || (LIST_EMPTY(&vp->v_dirtyblkhd) && - UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) { - vput(vp); - continue; - } - if (vp->v_type == VBLK && is_suspending) { - vput(vp); - continue; - } if (waitfor == MNT_LAZY) { error = UFS_WAPBL_BEGIN(vp->v_mount); if (!error) { Index: src/sys/ufs/lfs/ulfs_quota1.c diff -u src/sys/ufs/lfs/ulfs_quota1.c:1.7 src/sys/ufs/lfs/ulfs_quota1.c:1.8 --- src/sys/ufs/lfs/ulfs_quota1.c:1.7 Mon Mar 17 05:34:16 2014 +++ src/sys/ufs/lfs/ulfs_quota1.c Sat May 24 12:34:04 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_quota1.c,v 1.7 2014/03/17 09:34:16 hannken Exp $ */ +/* $NetBSD: ulfs_quota1.c,v 1.8 2014/05/24 16:34:04 christos Exp $ */ /* from NetBSD: ufs_quota1.c,v 1.18 2012/02/02 03:00:48 matt Exp */ /* @@ -36,7 +36,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ulfs_quota1.c,v 1.7 2014/03/17 09:34:16 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_quota1.c,v 1.8 2014/05/24 16:34:04 christos Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -370,7 +370,7 @@ lfsquota1_handle_cmd_quotaon(struct lwp * NB: only need to add dquot's for inodes being modified. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); @@ -434,7 +434,7 @@ lfsquota1_handle_cmd_quotaoff(struct lwp * deleting any references to quota file being closed. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); @@ -760,7 +760,7 @@ lfs_q1sync(struct mount *mp) * synchronizing any modified dquot structures. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); Index: src/sys/ufs/ufs/ufs_quota1.c diff -u src/sys/ufs/ufs/ufs_quota1.c:1.19 src/sys/ufs/ufs/ufs_quota1.c:1.20 --- src/sys/ufs/ufs/ufs_quota1.c:1.19 Mon Mar 17 05:31:35 2014 +++ src/sys/ufs/ufs/ufs_quota1.c Sat May 24 12:34:04 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_quota1.c,v 1.19 2014/03/17 09:31:35 hannken Exp $ */ +/* $NetBSD: ufs_quota1.c,v 1.20 2014/05/24 16:34:04 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1990, 1993, 1995 @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ufs_quota1.c,v 1.19 2014/03/17 09:31:35 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_quota1.c,v 1.20 2014/05/24 16:34:04 christos Exp $"); #include <sys/param.h> #include <sys/kernel.h> @@ -373,7 +373,7 @@ quota1_handle_cmd_quotaon(struct lwp *l, * NB: only need to add dquot's for inodes being modified. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); @@ -436,7 +436,7 @@ quota1_handle_cmd_quotaoff(struct lwp *l * deleting any references to quota file being closed. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp); @@ -762,7 +762,7 @@ q1sync(struct mount *mp) * synchronizing any modified dquot structures. */ vfs_vnode_iterator_init(mp, &marker); - while (vfs_vnode_iterator_next(marker, &vp)) { + while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { error = vn_lock(vp, LK_EXCLUSIVE); if (error) { vrele(vp);