diff --git a/sys/fs/nwfs/nwfs_vfsops.c b/sys/fs/nwfs/nwfs_vfsops.c index b37a856aaee6..2fb075296174 100644 --- a/sys/fs/nwfs/nwfs_vfsops.c +++ b/sys/fs/nwfs/nwfs_vfsops.c @@ -471,30 +471,41 @@ nwfs_sync(mp, waitfor, cred, p) struct ucred *cred; struct proc *p; { - struct vnode *vp; + struct vnode *vp, *nvp; int error, allerror = 0; /* * Force stale buffer cache information to be flushed. */ + mtx_lock(&mntvnode_mtx); loop: for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; - vp = LIST_NEXT(vp, v_mntvnodes)) { + vp = nvp) { /* * If the vnode that we are about to sync is no longer * associated with this mount point, start over. */ if (vp->v_mount != mp) goto loop; + nvp = LIST_NEXT(vp, v_mntvnodes); + mtx_unlock(&mntvnode_mtx); + mtx_lock(&vp->v_interlock); if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || - waitfor == MNT_LAZY) + waitfor == MNT_LAZY) { + mtx_unlock(&vp->v_interlock); + mtx_lock(&mntvnode_mtx); continue; - if (vget(vp, LK_EXCLUSIVE, p)) + } + if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) { + mtx_lock(&mntvnode_mtx); goto loop; + } error = VOP_FSYNC(vp, cred, waitfor, p); if (error) allerror = error; vput(vp); + mtx_lock(&mntvnode_mtx); } + mtx_unlock(&mntvnode_mtx); return (allerror); } diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c index 1a5cb7090e95..aa4986c276e1 100644 --- a/sys/fs/unionfs/union_vfsops.c +++ b/sys/fs/unionfs/union_vfsops.c @@ -45,6 +45,8 @@ #include #include #include +#include +#include #include #include #include @@ -330,9 +332,11 @@ union_unmount(mp, mntflags, p) int n; /* count #vnodes held on mount list */ + mtx_lock(&mntvnode_mtx); n = 0; LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) n++; + mtx_unlock(&mntvnode_mtx); /* if this is unchanged then stop */ if (n == freeing)