Module Name:    src
Committed By:   hannken
Date:           Wed Mar  5 09:37:29 UTC 2014

Modified Files:
        src/share/man/man9: vnode.9
        src/sys/kern: vfs_mount.c vfs_vnode.c
        src/sys/sys: mount.h param.h vnode.h
        src/sys/ufs/ext2fs: ext2fs_vfsops.c
        src/sys/ufs/ffs: ffs_vfsops.c
        src/sys/ufs/lfs: lfs_syscalls.c

Log Message:
Current support for iterating over mnt_vnodelist is rudimentary.  Every
caller has to care about list and vnode mutexes, reference count being zero,
intermediate vnode states like VI_CLEAN, VI_XLOCK, VI_MARKER and so on.

Add an interface to iterate over a vnode list:

void vfs_vnode_iterator_init(struct mount *mp, struct vnode_iterator **marker)
void vfs_vnode_iterator_destroy(struct vnode_iterator *marker)
bool vfs_vnode_iterator_next(struct vnode_iterator *marker, struct vnode **vpp)

vfs_vnode_iterator_next() returns either "false / *vpp == NULL" when done
or "true / *vpp != NULL" to return the next referenced vnode from the list.

To make vrecycle() work in this environment change it to

bool vrecycle(struct vnode *vp)

where "vp" is a referenced vnode to be destroyed if this is the last reference.

Discussed on tech-kern.

Welcome to 6.99.34


To generate a diff of this commit:
cvs rdiff -u -r1.59 -r1.60 src/share/man/man9/vnode.9
cvs rdiff -u -r1.26 -r1.27 src/sys/kern/vfs_mount.c
cvs rdiff -u -r1.32 -r1.33 src/sys/kern/vfs_vnode.c
cvs rdiff -u -r1.211 -r1.212 src/sys/sys/mount.h
cvs rdiff -u -r1.442 -r1.443 src/sys/sys/param.h
cvs rdiff -u -r1.243 -r1.244 src/sys/sys/vnode.h
cvs rdiff -u -r1.176 -r1.177 src/sys/ufs/ext2fs/ext2fs_vfsops.c
cvs rdiff -u -r1.292 -r1.293 src/sys/ufs/ffs/ffs_vfsops.c
cvs rdiff -u -r1.150 -r1.151 src/sys/ufs/lfs/lfs_syscalls.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man9/vnode.9
diff -u src/share/man/man9/vnode.9:1.59 src/share/man/man9/vnode.9:1.60
--- src/share/man/man9/vnode.9:1.59	Sat Feb 22 11:28:18 2014
+++ src/share/man/man9/vnode.9	Wed Mar  5 09:37:29 2014
@@ -1,4 +1,4 @@
-.\"     $NetBSD: vnode.9,v 1.59 2014/02/22 11:28:18 wiz Exp $
+.\"     $NetBSD: vnode.9,v 1.60 2014/03/05 09:37:29 hannken Exp $
 .\"
 .\" Copyright (c) 2001, 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 February 22, 2014
+.Dd March 5, 2014
 .Dt VNODE 9
 .Os
 .Sh NAME
@@ -79,7 +79,7 @@
 .Ft void
 .Fn ungetnewvnode "struct vnode *vp"
 .Ft int
-.Fn vrecycle "struct vnode *vp" "struct kmutex_t *inter_lkp"
+.Fn vrecycle "struct vnode *vp"
 .Ft void
 .Fn vgone "struct vnode *vp"
 .Ft void
@@ -616,12 +616,12 @@ This function is needed for
 .Xr VFS_VGET 9
 which may need to push back a vnode in case of a locking race
 condition.
-.It Fn vrecycle "vp" "inter_lkp"
-Recycle the unused vnode
+.It Fn vrecycle "vp"
+Recycle the referenced vnode
 .Fa vp
-from the front of the freelist.
+if this is the last reference.
 .Fn vrecycle
-is a null operation if the reference count is greater than zero.
+is a null operation if the reference count is greater than one.
 .It Fn vgone "vp"
 Eliminate all activity associated with the unlocked vnode
 .Fa vp

Index: src/sys/kern/vfs_mount.c
diff -u src/sys/kern/vfs_mount.c:1.26 src/sys/kern/vfs_mount.c:1.27
--- src/sys/kern/vfs_mount.c:1.26	Thu Feb 27 13:00:06 2014
+++ src/sys/kern/vfs_mount.c	Wed Mar  5 09:37:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_mount.c,v 1.26 2014/02/27 13:00:06 hannken Exp $	*/
+/*	$NetBSD: vfs_mount.c,v 1.27 2014/03/05 09:37:29 hannken 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.26 2014/02/27 13:00:06 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.27 2014/03/05 09:37:29 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -375,6 +375,82 @@ vunmark(vnode_t *mvp)
 	return vp;
 }
 
+struct vnode_iterator {
+	struct vnode vi_vnode;
+}; 
+
+void
+vfs_vnode_iterator_init(struct mount *mp, struct vnode_iterator **vipp)
+{
+	struct vnode *vp;
+
+	vp = vnalloc(mp);
+
+	mutex_enter(&mntvnode_lock);
+	TAILQ_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
+	vp->v_usecount = 1;
+	mutex_exit(&mntvnode_lock);
+
+	*vipp = (struct vnode_iterator *)vp;
+}
+
+void
+vfs_vnode_iterator_destroy(struct vnode_iterator *vi)
+{
+	struct vnode *mvp = &vi->vi_vnode;
+
+	mutex_enter(&mntvnode_lock);
+	KASSERT(ISSET(mvp->v_iflag, VI_MARKER));
+	if (mvp->v_usecount != 0)
+		TAILQ_REMOVE(&mvp->v_mount->mnt_vnodelist, mvp, v_mntvnodes);
+	mutex_exit(&mntvnode_lock);
+	vnfree(mvp);
+}
+
+bool
+vfs_vnode_iterator_next(struct vnode_iterator *vi, struct vnode **vpp)
+{
+	struct vnode *mvp = &vi->vi_vnode;
+	struct mount *mp = mvp->v_mount;
+	struct vnode *vp;
+	int error;
+
+	KASSERT(ISSET(mvp->v_iflag, VI_MARKER));
+
+	do {
+		mutex_enter(&mntvnode_lock);
+		vp = TAILQ_NEXT(mvp, v_mntvnodes);
+		TAILQ_REMOVE(&mp->mnt_vnodelist, mvp, v_mntvnodes);
+		mvp->v_usecount = 0;
+		if (vp == NULL) {
+	       		mutex_exit(&mntvnode_lock);
+			*vpp = NULL;
+	       		return false;
+		}
+
+		mutex_enter(vp->v_interlock);
+		while ((vp->v_iflag & VI_MARKER) != 0) {
+			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);
+		}
+
+		TAILQ_INSERT_AFTER(&mp->mnt_vnodelist, vp, mvp, v_mntvnodes);
+		mvp->v_usecount = 1;
+		mutex_exit(&mntvnode_lock);
+		error = vget(vp, 0);
+		KASSERT(error == 0 || error == ENOENT);
+	} while (error != 0);
+
+	*vpp = vp;
+	return true;
+}
+
 /*
  * Move a vnode from one mount queue to another.
  */
@@ -426,99 +502,78 @@ struct ctldebug debug1 = { "busyprt", &b
 #endif
 
 static vnode_t *
-vflushnext(vnode_t *mvp, int *when)
+vflushnext(struct vnode_iterator *marker, int *when)
 {
+	struct vnode *vp;
 
 	if (hardclock_ticks > *when) {
-		mutex_exit(&mntvnode_lock);
 		yield();
-		mutex_enter(&mntvnode_lock);
 		*when = hardclock_ticks + hz / 10;
 	}
-	return vunmark(mvp);
+	if (vfs_vnode_iterator_next(marker, &vp))
+		return vp;
+	return NULL;
 }
 
 int
 vflush(struct mount *mp, vnode_t *skipvp, int flags)
 {
-	vnode_t *vp, *mvp;
+	vnode_t *vp;
+	struct vnode_iterator *marker;
 	int busy = 0, when = 0;
 
 	/* First, flush out any vnode references from vrele_list. */
 	vrele_flush();
 
-	/* Allocate a marker vnode. */
-	mvp = vnalloc(mp);
-
-	/*
-	 * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
-	 * and vclean() are called.
-	 */
-	mutex_enter(&mntvnode_lock);
-	for (vp = TAILQ_FIRST(&mp->mnt_vnodelist);
-	    vp != NULL;
-	    vp = vflushnext(mvp, &when)) {
-		vmark(mvp, vp);
-		if (vp->v_mount != mp || vismarker(vp))
-			continue;
+	vfs_vnode_iterator_init(mp, &marker);
+	while ((vp = vflushnext(marker, &when)) != NULL) {
 		/*
 		 * Skip over a selected vnode.
 		 */
-		if (vp == skipvp)
-			continue;
-		/*
-		 * First try to recycle the vnode.
-		 */
-		if (vrecycle(vp, &mntvnode_lock)) {
-			mutex_enter(&mntvnode_lock);
-			continue;
-		}
-		mutex_enter(vp->v_interlock);
-		/*
-		 * Ignore clean but still referenced vnodes.
-		 */
-		if ((vp->v_iflag & VI_CLEAN) != 0) {
-			mutex_exit(vp->v_interlock);
+		if (vp == skipvp) {
+			vrele(vp);
 			continue;
 		}
 		/*
 		 * Skip over a vnodes marked VSYSTEM.
 		 */
 		if ((flags & SKIPSYSTEM) && (vp->v_vflag & VV_SYSTEM)) {
-			mutex_exit(vp->v_interlock);
+			vrele(vp);
 			continue;
 		}
 		/*
 		 * If WRITECLOSE is set, only flush out regular file
 		 * vnodes open for writing.
 		 */
-		if ((flags & WRITECLOSE) &&
-		    (vp->v_writecount == 0 || vp->v_type != VREG)) {
+		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);
-			continue;
 		}
 		/*
+		 * First try to recycle the vnode.
+		 */
+		if (vrecycle(vp))
+			continue;
+		/*
 		 * If FORCECLOSE is set, forcibly close the vnode.
-		 * For block or character devices, revert to an
-		 * anonymous device.  For all other files, just
-		 * kill them.
 		 */
 		if (flags & FORCECLOSE) {
-			mutex_exit(&mntvnode_lock);
-			if (vget(vp, 0) == 0)
-				vgone(vp);
-			mutex_enter(&mntvnode_lock);
+			vgone(vp);
 			continue;
 		}
 #ifdef DEBUG
 		if (busyprt)
 			vprint("vflush: busy vnode", vp);
 #endif
-		mutex_exit(vp->v_interlock);
+		vrele(vp);
 		busy++;
 	}
-	mutex_exit(&mntvnode_lock);
-	vnfree(mvp);
+	vfs_vnode_iterator_destroy(marker);
 	if (busy)
 		return (EBUSY);
 	return (0);

Index: src/sys/kern/vfs_vnode.c
diff -u src/sys/kern/vfs_vnode.c:1.32 src/sys/kern/vfs_vnode.c:1.33
--- src/sys/kern/vfs_vnode.c:1.32	Thu Feb 27 16:51:38 2014
+++ src/sys/kern/vfs_vnode.c	Wed Mar  5 09:37:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_vnode.c,v 1.32 2014/02/27 16:51:38 hannken Exp $	*/
+/*	$NetBSD: vfs_vnode.c,v 1.33 2014/03/05 09:37:29 hannken Exp $	*/
 
 /*-
  * Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
@@ -116,7 +116,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.32 2014/02/27 16:51:38 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.33 2014/03/05 09:37:29 hannken Exp $");
 
 #define _VFS_VNODE_PRIVATE
 
@@ -1029,30 +1029,33 @@ vclean(vnode_t *vp)
 }
 
 /*
- * Recycle an unused vnode to the front of the free list.
- * Release the passed interlock if the vnode will be recycled.
+ * Recycle an unused vnode if caller holds the last reference.
  */
-int
-vrecycle(vnode_t *vp, kmutex_t *inter_lkp)
+bool
+vrecycle(vnode_t *vp)
 {
 
+	mutex_enter(vp->v_interlock);
+
 	KASSERT((vp->v_iflag & VI_MARKER) == 0);
 
-	mutex_enter(vp->v_interlock);
-	if (vp->v_usecount != 0 || (vp->v_iflag & (VI_CLEAN|VI_XLOCK)) != 0) {
+	if (vp->v_usecount != 1) {
 		mutex_exit(vp->v_interlock);
-		return 0;
+		return false;
 	}
-	if (inter_lkp) {
-		mutex_exit(inter_lkp);
+	if ((vp->v_iflag & VI_CHANGING) != 0)
+		vwait(vp, VI_CHANGING);
+	if (vp->v_usecount != 1) {
+		mutex_exit(vp->v_interlock);
+		return false;
+	} else if ((vp->v_iflag & VI_CLEAN) != 0) {
+		mutex_exit(vp->v_interlock);
+		return true;
 	}
-	vremfree(vp);
-	vp->v_usecount = 1;
-	KASSERT((vp->v_iflag & VI_CHANGING) == 0);
 	vp->v_iflag |= VI_CHANGING;
 	vclean(vp);
 	vrelel(vp, VRELEL_CHANGING_SET);
-	return 1;
+	return true;
 }
 
 /*

Index: src/sys/sys/mount.h
diff -u src/sys/sys/mount.h:1.211 src/sys/sys/mount.h:1.212
--- src/sys/sys/mount.h:1.211	Thu Feb 27 13:00:06 2014
+++ src/sys/sys/mount.h	Wed Mar  5 09:37:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: mount.h,v 1.211 2014/02/27 13:00:06 hannken Exp $	*/
+/*	$NetBSD: mount.h,v 1.212 2014/03/05 09:37:29 hannken Exp $	*/
 
 /*
  * Copyright (c) 1989, 1991, 1993
@@ -433,6 +433,11 @@ int	vfs_quotactl_cursorrewind(struct mou
 int	vfs_quotactl_quotaon(struct mount *, int, const char *);
 int	vfs_quotactl_quotaoff(struct mount *, int);
 
+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 **);
+
 extern	TAILQ_HEAD(mntlist, mount) mountlist;	/* mounted filesystem list */
 extern	struct vfsops *vfssw[];			/* filesystem type table */
 extern	int nvfssw;

Index: src/sys/sys/param.h
diff -u src/sys/sys/param.h:1.442 src/sys/sys/param.h:1.443
--- src/sys/sys/param.h:1.442	Thu Feb 27 16:51:39 2014
+++ src/sys/sys/param.h	Wed Mar  5 09:37:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: param.h,v 1.442 2014/02/27 16:51:39 hannken Exp $	*/
+/*	$NetBSD: param.h,v 1.443 2014/03/05 09:37:29 hannken Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -63,7 +63,7 @@
  *	2.99.9		(299000900)
  */
 
-#define	__NetBSD_Version__	699003300	/* NetBSD 6.99.33 */
+#define	__NetBSD_Version__	699003400	/* NetBSD 6.99.34 */
 
 #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
     (m) * 1000000) + (p) * 100) <= __NetBSD_Version__)

Index: src/sys/sys/vnode.h
diff -u src/sys/sys/vnode.h:1.243 src/sys/sys/vnode.h:1.244
--- src/sys/sys/vnode.h:1.243	Sun Dec  1 17:29:40 2013
+++ src/sys/sys/vnode.h	Wed Mar  5 09:37:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: vnode.h,v 1.243 2013/12/01 17:29:40 christos Exp $	*/
+/*	$NetBSD: vnode.h,v 1.244 2014/03/05 09:37:29 hannken Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -545,7 +545,7 @@ void 	vgone(struct vnode *);
 int	vinvalbuf(struct vnode *, int, kauth_cred_t, struct lwp *, bool, int);
 void	vprint(const char *, struct vnode *);
 void 	vput(struct vnode *);
-int	vrecycle(struct vnode *, kmutex_t *);
+bool	vrecycle(struct vnode *);
 void 	vrele(struct vnode *);
 void 	vrele_async(struct vnode *);
 void	vrele_flush(void);

Index: src/sys/ufs/ext2fs/ext2fs_vfsops.c
diff -u src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.176 src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.177
--- src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.176	Tue Feb 25 18:30:13 2014
+++ src/sys/ufs/ext2fs/ext2fs_vfsops.c	Wed Mar  5 09:37:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_vfsops.c,v 1.176 2014/02/25 18:30:13 pooka Exp $	*/
+/*	$NetBSD: ext2fs_vfsops.c,v 1.177 2014/03/05 09:37:29 hannken Exp $	*/
 
 /*
  * Copyright (c) 1989, 1991, 1993, 1994
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.176 2014/02/25 18:30:13 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.177 2014/03/05 09:37:29 hannken Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -512,7 +512,7 @@ fail:
 int
 ext2fs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
 {
-	struct vnode *vp, *mvp, *devvp;
+	struct vnode *vp, *devvp;
 	struct inode *ip;
 	struct buf *bp;
 	struct m_ext2fs *fs;
@@ -520,6 +520,7 @@ ext2fs_reload(struct mount *mp, kauth_cr
 	int i, error;
 	void *cp;
 	struct ufsmount *ump;
+	struct vnode_iterator *marker;
 
 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
 		return (EINVAL);
@@ -585,35 +586,19 @@ ext2fs_reload(struct mount *mp, kauth_cr
 		brelse(bp, 0);
 	}
 
-	/* Allocate a marker vnode. */
-	mvp = vnalloc(mp);
-	/*
-	 * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
-	 * and vclean() can be called indirectly
-	 */
-	mutex_enter(&mntvnode_lock);
-loop:
-	for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) {
-		vmark(mvp, vp);
-		if (vp->v_mount != mp || vismarker(vp))
-			continue;
+	vfs_vnode_iterator_init(mp, &marker);
+	while (vfs_vnode_iterator_next(marker, &vp)) {
 		/*
 		 * Step 4: invalidate all inactive vnodes.
 		 */
-		if (vrecycle(vp, &mntvnode_lock)) {
-			mutex_enter(&mntvnode_lock);
-			(void)vunmark(mvp);
-			goto loop;
-		}
+		if (vrecycle(vp))
+			continue;
 		/*
 		 * Step 5: invalidate all cached file data.
 		 */
-		mutex_enter(vp->v_interlock);
-		mutex_exit(&mntvnode_lock);
-		if (vget(vp, LK_EXCLUSIVE)) {
-			mutex_enter(&mntvnode_lock);
-			(void)vunmark(mvp);
-			goto loop;
+		if (vn_lock(vp, LK_EXCLUSIVE)) {
+			vrele(vp);
+			continue;
 		}
 		if (vinvalbuf(vp, 0, cred, l, 0, 0))
 			panic("ext2fs_reload: dirty2");
@@ -625,8 +610,6 @@ loop:
 		    (int)fs->e2fs_bsize, NOCRED, 0, &bp);
 		if (error) {
 			vput(vp);
-			mutex_enter(&mntvnode_lock);
-			(void)vunmark(mvp);
 			break;
 		}
 		cp = (char *)bp->b_data +
@@ -635,10 +618,8 @@ loop:
 		ext2fs_set_inode_guid(ip);
 		brelse(bp, 0);
 		vput(vp);
-		mutex_enter(&mntvnode_lock);
 	}
-	mutex_exit(&mntvnode_lock);
-	vnfree(mvp);
+	vfs_vnode_iterator_destroy(marker);
 	return (error);
 }
 

Index: src/sys/ufs/ffs/ffs_vfsops.c
diff -u src/sys/ufs/ffs/ffs_vfsops.c:1.292 src/sys/ufs/ffs/ffs_vfsops.c:1.293
--- src/sys/ufs/ffs/ffs_vfsops.c:1.292	Tue Feb 25 18:30:13 2014
+++ src/sys/ufs/ffs/ffs_vfsops.c	Wed Mar  5 09:37:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ffs_vfsops.c,v 1.292 2014/02/25 18:30:13 pooka Exp $	*/
+/*	$NetBSD: ffs_vfsops.c,v 1.293 2014/03/05 09:37:29 hannken 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.292 2014/02/25 18:30:13 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.293 2014/03/05 09:37:29 hannken Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -636,7 +636,7 @@ fail:
 int
 ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
 {
-	struct vnode *vp, *mvp, *devvp;
+	struct vnode *vp, *devvp;
 	struct inode *ip;
 	void *space;
 	struct buf *bp;
@@ -646,6 +646,7 @@ ffs_reload(struct mount *mp, kauth_cred_
 	int32_t *lp;
 	struct ufsmount *ump;
 	daddr_t sblockloc;
+	struct vnode_iterator *marker;
 
 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
 		return (EINVAL);
@@ -805,34 +806,19 @@ ffs_reload(struct mount *mp, kauth_cred_
 			*lp++ = fs->fs_contigsumsize;
 	}
 
-	/* Allocate a marker vnode. */
-	mvp = vnalloc(mp);
-	/*
-	 * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
-	 * and vclean() can be called indirectly
-	 */
-	mutex_enter(&mntvnode_lock);
- loop:
-	for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) {
-		vmark(mvp, vp);
-		if (vp->v_mount != mp || vismarker(vp))
-			continue;
+	vfs_vnode_iterator_init(mp, &marker);
+	while (vfs_vnode_iterator_next(marker, &vp)) {
 		/*
 		 * Step 4: invalidate all inactive vnodes.
 		 */
-		if (vrecycle(vp, &mntvnode_lock)) {
-			mutex_enter(&mntvnode_lock);
-			(void)vunmark(mvp);
-			goto loop;
-		}
+		if (vrecycle(vp))
+			continue;
 		/*
 		 * Step 5: invalidate all cached file data.
 		 */
-		mutex_enter(vp->v_interlock);
-		mutex_exit(&mntvnode_lock);
-		if (vget(vp, LK_EXCLUSIVE)) {
-			(void)vunmark(mvp);
-			goto loop;
+		if (vn_lock(vp, LK_EXCLUSIVE)) {
+			vrele(vp);
+			continue;
 		}
 		if (vinvalbuf(vp, 0, cred, l, 0, 0))
 			panic("ffs_reload: dirty2");
@@ -844,16 +830,13 @@ ffs_reload(struct mount *mp, kauth_cred_
 			      (int)fs->fs_bsize, NOCRED, 0, &bp);
 		if (error) {
 			vput(vp);
-			(void)vunmark(mvp);
 			break;
 		}
 		ffs_load_inode(bp, ip, fs, ip->i_number);
 		brelse(bp, 0);
 		vput(vp);
-		mutex_enter(&mntvnode_lock);
 	}
-	mutex_exit(&mntvnode_lock);
-	vnfree(mvp);
+	vfs_vnode_iterator_destroy(marker);
 	return (error);
 }
 

Index: src/sys/ufs/lfs/lfs_syscalls.c
diff -u src/sys/ufs/lfs/lfs_syscalls.c:1.150 src/sys/ufs/lfs/lfs_syscalls.c:1.151
--- src/sys/ufs/lfs/lfs_syscalls.c:1.150	Tue Oct 29 09:53:51 2013
+++ src/sys/ufs/lfs/lfs_syscalls.c	Wed Mar  5 09:37:29 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_syscalls.c,v 1.150 2013/10/29 09:53:51 hannken Exp $	*/
+/*	$NetBSD: lfs_syscalls.c,v 1.151 2014/03/05 09:37:29 hannken Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007, 2008
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.150 2013/10/29 09:53:51 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.151 2014/03/05 09:37:29 hannken Exp $");
 
 #ifndef LFS
 # define LFS		/* for prototypes in syscallargs.h */
@@ -712,8 +712,13 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp,
 			 */
 			if (v_daddr != LFS_UNUSED_DADDR) {
 				lfs_vunref(vp);
-				if (VTOI(vp)->i_lfs_iflags & LFSI_BMAP)
-					vrecycle(vp, NULL);
+				if (VTOI(vp)->i_lfs_iflags & LFSI_BMAP) {
+					mutex_enter(vp->v_interlock);
+					if (vget(vp, LK_NOWAIT) == 0) {
+						if (! vrecycle(vp))
+							vrele(vp);
+					}
+				}
 				numrefed--;
 			}
 
@@ -822,8 +827,13 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp,
 	if (v_daddr != LFS_UNUSED_DADDR) {
 		lfs_vunref(vp);
 		/* Recycle as above. */
-		if (ip->i_lfs_iflags & LFSI_BMAP)
-			vrecycle(vp, NULL);
+		if (ip->i_lfs_iflags & LFSI_BMAP) {
+			mutex_enter(vp->v_interlock);
+			if (vget(vp, LK_NOWAIT) == 0) {
+				if (! vrecycle(vp))
+					vrele(vp);
+			}
+		}
 		numrefed--;
 	}
 

Reply via email to