diff options
author | tegge <tegge@FreeBSD.org> | 2006-01-09 20:42:19 +0000 |
---|---|---|
committer | tegge <tegge@FreeBSD.org> | 2006-01-09 20:42:19 +0000 |
commit | d344c1186100b5323aefd8a08d585a95db5aa73c (patch) | |
tree | 63c09ce208013c75e9755db86cfe31120c538d27 | |
parent | 4d88aab3ea1d28d6617480348f596c37389d6434 (diff) | |
download | FreeBSD-src-d344c1186100b5323aefd8a08d585a95db5aa73c.zip FreeBSD-src-d344c1186100b5323aefd8a08d585a95db5aa73c.tar.gz |
Add marker vnodes to ensure that all vnodes associated with the mount point are
iterated over when using MNT_VNODE_FOREACH.
Reviewed by: truckman
-rw-r--r-- | sys/fs/cd9660/cd9660_vnops.c | 1 | ||||
-rw-r--r-- | sys/gnu/fs/ext2fs/ext2_vfsops.c | 14 | ||||
-rw-r--r-- | sys/isofs/cd9660/cd9660_vnops.c | 1 | ||||
-rw-r--r-- | sys/kern/vfs_default.c | 8 | ||||
-rw-r--r-- | sys/kern/vfs_mount.c | 122 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 39 | ||||
-rw-r--r-- | sys/nfs4client/nfs4_vfsops.c | 5 | ||||
-rw-r--r-- | sys/nfsclient/nfs_vfsops.c | 5 | ||||
-rw-r--r-- | sys/sys/mount.h | 22 | ||||
-rw-r--r-- | sys/sys/vnode.h | 3 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_snapshot.c | 6 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 14 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_quota.c | 22 | ||||
-rw-r--r-- | usr.bin/fstat/fstat.c | 1 |
14 files changed, 197 insertions, 66 deletions
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c index e4f6336..3e67000 100644 --- a/sys/fs/cd9660/cd9660_vnops.c +++ b/sys/fs/cd9660/cd9660_vnops.c @@ -108,6 +108,7 @@ cd9660_setattr(ap) case VFIFO: case VNON: case VBAD: + case VMARKER: return (0); } } diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c index 400b308..1bccb61 100644 --- a/sys/gnu/fs/ext2fs/ext2_vfsops.c +++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c @@ -501,7 +501,7 @@ static int compute_sb_data(devvp, es, fs) static int ext2_reload(struct mount *mp, struct thread *td) { - struct vnode *vp, *nvp, *devvp; + struct vnode *vp, *mvp, *devvp; struct inode *ip; struct buf *bp; struct ext2_super_block * es; @@ -545,7 +545,7 @@ ext2_reload(struct mount *mp, struct thread *td) loop: MNT_ILOCK(mp); - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); if (vp->v_iflag & VI_DOOMED) { VI_UNLOCK(vp); @@ -556,6 +556,7 @@ loop: * Step 4: invalidate all cached file data. */ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { + MNT_VNODE_FOREACH_ABORT(mp, mvp); goto loop; } if (vinvalbuf(vp, 0, td, 0, 0)) @@ -570,6 +571,7 @@ loop: if (error) { VOP_UNLOCK(vp, 0, td); vrele(vp); + MNT_VNODE_FOREACH_ABORT(mp, mvp); return (error); } ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data + @@ -855,7 +857,7 @@ ext2_sync(mp, waitfor, td) int waitfor; struct thread *td; { - struct vnode *nvp, *vp; + struct vnode *mvp, *vp; struct inode *ip; struct ext2mount *ump = VFSTOEXT2(mp); struct ext2_sb_info *fs; @@ -871,7 +873,7 @@ ext2_sync(mp, waitfor, td) */ MNT_ILOCK(mp); loop: - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); if (vp->v_type == VNON || (vp->v_iflag & VI_DOOMED)) { VI_UNLOCK(vp); @@ -890,8 +892,10 @@ loop: error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td); if (error) { MNT_ILOCK(mp); - if (error == ENOENT) + if (error == ENOENT) { + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto loop; + } continue; } if ((error = VOP_FSYNC(vp, waitfor, td)) != 0) diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c index e4f6336..3e67000 100644 --- a/sys/isofs/cd9660/cd9660_vnops.c +++ b/sys/isofs/cd9660/cd9660_vnops.c @@ -108,6 +108,7 @@ cd9660_setattr(ap) case VFIFO: case VNON: case VBAD: + case VMARKER: return (0); } } diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index d8adf7c..be8c931 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -545,7 +545,7 @@ vfs_stdsync(mp, waitfor, td) int waitfor; struct thread *td; { - struct vnode *vp, *nvp; + struct vnode *vp, *mvp; int error, lockreq, allerror = 0; lockreq = LK_EXCLUSIVE | LK_INTERLOCK; @@ -556,7 +556,7 @@ vfs_stdsync(mp, waitfor, td) */ MNT_ILOCK(mp); loop: - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); if (vp->v_bufobj.bo_dirty.bv_cnt == 0) { @@ -567,8 +567,10 @@ loop: if ((error = vget(vp, lockreq, td)) != 0) { MNT_ILOCK(mp); - if (error == ENOENT) + if (error == ENOENT) { + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto loop; + } continue; } error = VOP_FSYNC(vp, waitfor, td); diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index ee8c1dc..b7b31a8 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -90,6 +90,7 @@ SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, "Unprivileged users may mount and unmount file systems"); MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure"); +MALLOC_DEFINE(M_VNODE_MARKER, "vnodemarker", "vnode marker"); /* List of mounted filesystems. */ struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist); @@ -445,6 +446,28 @@ static void vfs_mount_destroy(struct mount *mp, struct thread *td) { + MNT_ILOCK(mp); + if (mp->mnt_holdcnt != 0) { + printf("Waiting for mount point to be unheld\n"); + while (mp->mnt_holdcnt != 0) { + mp->mnt_holdcntwaiters++; + msleep(&mp->mnt_holdcnt, MNT_MTX(mp), + PZERO, "mntdestroy", 0); + mp->mnt_holdcntwaiters--; + } + printf("mount point unheld\n"); + } + if (mp->mnt_writeopcount > 0) { + printf("Waiting for mount point write ops\n"); + while (mp->mnt_writeopcount > 0) { + mp->mnt_kern_flag |= MNTK_SUSPEND; + msleep(&mp->mnt_writeopcount, + MNT_MTX(mp), + PZERO, "mntdestroy2", 0); + } + printf("mount point write ops completed\n"); + } + MNT_IUNLOCK(mp); mp->mnt_vfc->vfc_refcount--; if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) panic("unmount: dangling vnode"); @@ -453,6 +476,12 @@ vfs_mount_destroy(struct mount *mp, struct thread *td) MNT_ILOCK(mp); if (mp->mnt_kern_flag & MNTK_MWAIT) wakeup(mp); + if (mp->mnt_writeopcount != 0) + panic("vfs_mount_destroy: nonzero writeopcount"); + if (mp->mnt_nvnodelistsize != 0) + panic("vfs_mount_destroy: nonzero nvnodelistsize"); + mp->mnt_writeopcount = -1000; + mp->mnt_nvnodelistsize = -1000; MNT_IUNLOCK(mp); mtx_destroy(&mp->mnt_mtx); #ifdef MAC @@ -1658,27 +1687,96 @@ vfs_copyopt(opts, name, dest, len) */ struct vnode * -__mnt_vnode_next(struct vnode **nvp, struct mount *mp) +__mnt_vnode_next(struct vnode **mvp, struct mount *mp) { struct vnode *vp; - mtx_assert(&mp->mnt_mtx, MA_OWNED); + mtx_assert(MNT_MTX(mp), MA_OWNED); - vp = *nvp; + KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch")); + vp = TAILQ_NEXT(*mvp, v_nmntvnodes); + while (vp != NULL && vp->v_type == VMARKER) + vp = TAILQ_NEXT(vp, v_nmntvnodes); + /* Check if we are done */ - if (vp == NULL) + if (vp == NULL) { + __mnt_vnode_markerfree(mvp, mp); return (NULL); - /* If our next vnode is no longer ours, start over */ - if (vp->v_mount != mp) - vp = TAILQ_FIRST(&mp->mnt_nvnodelist); - /* Save pointer to next vnode in list */ - if (vp != NULL) - *nvp = TAILQ_NEXT(vp, v_nmntvnodes); - else - *nvp = NULL; + } + TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes); + TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes); return (vp); } +struct vnode * +__mnt_vnode_first(struct vnode **mvp, struct mount *mp) +{ + struct vnode *vp; + + mtx_assert(MNT_MTX(mp), MA_OWNED); + + vp = TAILQ_FIRST(&mp->mnt_nvnodelist); + while (vp != NULL && vp->v_type == VMARKER) + vp = TAILQ_NEXT(vp, v_nmntvnodes); + + /* Check if we are done */ + if (vp == NULL) { + *mvp = NULL; + return (NULL); + } + mp->mnt_holdcnt++; + MNT_IUNLOCK(mp); + *mvp = (struct vnode *) malloc(sizeof(struct vnode), + M_VNODE_MARKER, + M_WAITOK | M_ZERO); + MNT_ILOCK(mp); + (*mvp)->v_type = VMARKER; + + vp = TAILQ_FIRST(&mp->mnt_nvnodelist); + while (vp != NULL && vp->v_type == VMARKER) + vp = TAILQ_NEXT(vp, v_nmntvnodes); + + /* Check if we are done */ + if (vp == NULL) { + MNT_IUNLOCK(mp); + free(*mvp, M_VNODE_MARKER); + MNT_ILOCK(mp); + *mvp = NULL; + mp->mnt_holdcnt--; + if (mp->mnt_holdcnt == 0 && mp->mnt_holdcntwaiters != 0) + wakeup(&mp->mnt_holdcnt); + return (NULL); + } + mp->mnt_markercnt++; + (*mvp)->v_mount = mp; + TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes); + return (vp); +} + + +void +__mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp) +{ + + if (*mvp == NULL) + return; + + mtx_assert(MNT_MTX(mp), MA_OWNED); + + KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch")); + TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes); + MNT_IUNLOCK(mp); + free(*mvp, M_VNODE_MARKER); + MNT_ILOCK(mp); + *mvp = NULL; + + mp->mnt_markercnt--; + mp->mnt_holdcnt--; + if (mp->mnt_holdcnt == 0 && mp->mnt_holdcntwaiters != 0) + wakeup(&mp->mnt_holdcnt); +} + + int __vfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) { diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index a57b2ba..629e22d 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -134,9 +134,9 @@ enum vtype iftovt_tab[16] = { VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD, }; -int vttoif_tab[9] = { +int vttoif_tab[10] = { 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, - S_IFSOCK, S_IFIFO, S_IFMT, + S_IFSOCK, S_IFIFO, S_IFMT, S_IFMT }; /* @@ -566,7 +566,12 @@ vlrureclaim(struct mount *mp) vn_start_write(NULL, &mp, V_WAIT); MNT_ILOCK(mp); count = mp->mnt_nvnodelistsize / 10 + 1; - while (count && (vp = TAILQ_FIRST(&mp->mnt_nvnodelist)) != NULL) { + while (count != 0) { + vp = TAILQ_FIRST(&mp->mnt_nvnodelist); + while (vp != NULL && vp->v_type == VMARKER) + vp = TAILQ_NEXT(vp, v_nmntvnodes); + if (vp == NULL) + break; TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes); TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes); --count; @@ -968,6 +973,8 @@ insmntque(struct vnode *vp, struct mount *mp) VNASSERT(mp != NULL, vp, ("Don't call insmntque(foo, NULL)")); MNT_ILOCK(vp->v_mount); TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes); + VNASSERT(mp->mnt_nvnodelistsize >= 0, vp, + ("neg mount point vnode list size")); mp->mnt_nvnodelistsize++; MNT_IUNLOCK(vp->v_mount); } @@ -2241,7 +2248,7 @@ vflush(mp, rootrefs, flags, td) int flags; struct thread *td; { - struct vnode *vp, *nvp, *rootvp = NULL; + struct vnode *vp, *mvp, *rootvp = NULL; struct vattr vattr; int busy = 0, error; @@ -2260,7 +2267,7 @@ vflush(mp, rootrefs, flags, td) } MNT_ILOCK(mp); loop: - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); vholdl(vp); @@ -2269,6 +2276,7 @@ loop: if (error) { vdrop(vp); MNT_ILOCK(mp); + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto loop; } /* @@ -2489,7 +2497,8 @@ count_dev(dev) * Print out a description of a vnode. */ static char *typename[] = -{"VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD"}; +{"VNON", "VREG", "VDIR", "VBLK", "VCHR", "VLNK", "VSOCK", "VFIFO", "VBAD", + "VMARKER"}; void vn_printf(struct vnode *vp, const char *fmt, ...) @@ -2818,20 +2827,11 @@ vfs_unmountall() void vfs_msync(struct mount *mp, int flags) { - struct vnode *vp, *nvp; + struct vnode *vp, *mvp; struct vm_object *obj; - int tries; - tries = 5; MNT_ILOCK(mp); -loop: - TAILQ_FOREACH_SAFE(vp, &mp->mnt_nvnodelist, v_nmntvnodes, nvp) { - if (vp->v_mount != mp) { - if (--tries > 0) - goto loop; - break; - } - + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); if ((vp->v_iflag & VI_OBJDIRTY) && (flags == MNT_WAIT || VOP_ISLOCKED(vp, NULL) == 0)) { @@ -2856,11 +2856,6 @@ loop: vput(vp); } MNT_ILOCK(mp); - if (TAILQ_NEXT(vp, v_nmntvnodes) != nvp) { - if (--tries > 0) - goto loop; - break; - } } else VI_UNLOCK(vp); } diff --git a/sys/nfs4client/nfs4_vfsops.c b/sys/nfs4client/nfs4_vfsops.c index 1e4968c..7673e01 100644 --- a/sys/nfs4client/nfs4_vfsops.c +++ b/sys/nfs4client/nfs4_vfsops.c @@ -733,7 +733,7 @@ nfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td) static int nfs_sync(struct mount *mp, int waitfor, struct thread *td) { - struct vnode *vp, *nvp; + struct vnode *vp, *mvp; int error, allerror = 0; /* @@ -741,7 +741,7 @@ nfs_sync(struct mount *mp, int waitfor, struct thread *td) */ MNT_ILOCK(mp); loop: - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); MNT_IUNLOCK(mp); if (VOP_ISLOCKED(vp, NULL) || @@ -753,6 +753,7 @@ loop: } if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { MNT_ILOCK(mp); + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto loop; } error = VOP_FSYNC(vp, waitfor, td); diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index 6f1db8d..be02893 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -981,7 +981,7 @@ nfs_root(struct mount *mp, int flags, struct vnode **vpp, struct thread *td) static int nfs_sync(struct mount *mp, int waitfor, struct thread *td) { - struct vnode *vp, *nvp; + struct vnode *vp, *mvp; int error, allerror = 0; /* @@ -989,7 +989,7 @@ nfs_sync(struct mount *mp, int waitfor, struct thread *td) */ MNT_ILOCK(mp); loop: - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); MNT_IUNLOCK(mp); if (VOP_ISLOCKED(vp, NULL) || @@ -1001,6 +1001,7 @@ loop: } if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { MNT_ILOCK(mp); + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto loop; } error = VOP_FSYNC(vp, waitfor, td); diff --git a/sys/sys/mount.h b/sys/sys/mount.h index bd9351b..ccec2fc 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -160,14 +160,28 @@ struct mount { struct label *mnt_fslabel; /* MAC label for the fs */ int mnt_nvnodelistsize; /* # of vnodes on this mount */ u_int mnt_hashseed; /* Random seed for vfs_hash */ + int mnt_markercnt; /* marker vnodes in use */ + int mnt_holdcnt; /* hold count */ + int mnt_holdcntwaiters; /* waits on hold count */ }; -struct vnode *__mnt_vnode_next(struct vnode **nvp, struct mount *mp); +struct vnode *__mnt_vnode_next(struct vnode **mvp, struct mount *mp); +struct vnode *__mnt_vnode_first(struct vnode **mvp, struct mount *mp); +void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp); -#define MNT_VNODE_FOREACH(vp, mp, vp2) \ - for ((vp2) = TAILQ_FIRST(&(mp)->mnt_nvnodelist); \ - (vp = __mnt_vnode_next(&(vp2), (mp))) != NULL;) +#define MNT_VNODE_FOREACH(vp, mp, mvp) \ + for (vp = __mnt_vnode_first(&(mvp), (mp)); \ + (vp) != NULL; vp = __mnt_vnode_next(&(mvp), (mp))) +#define MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp) \ + __mnt_vnode_markerfree(&(mvp), (mp)) + +#define MNT_VNODE_FOREACH_ABORT(mp, mvp) \ + do { \ + MNT_ILOCK(mp); \ + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); \ + MNT_IUNLOCK(mp); \ + } while (0) #define MNT_ILOCK(mp) mtx_lock(&(mp)->mnt_mtx) #define MNT_IUNLOCK(mp) mtx_unlock(&(mp)->mnt_mtx) diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 6c93439..d6bd2dd 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -59,7 +59,8 @@ /* * Vnode types. VNON means no type. */ -enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD }; +enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD, + VMARKER }; /* * Each underlying filesystem allocates its own private area and hangs diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index c64a1e3..355c19f 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -203,7 +203,7 @@ ffs_snapshot(mp, snapfile) struct nameidata nd; struct mount *wrtmp; struct vattr vat; - struct vnode *vp, *xvp, *nvp, *devvp; + struct vnode *vp, *xvp, *mvp, *devvp; struct uio auio; struct iovec aiov; struct snapdata *sn; @@ -485,7 +485,7 @@ restart: MNT_ILOCK(mp); mp->mnt_kern_flag &= ~MNTK_SUSPENDED; loop: - MNT_VNODE_FOREACH(xvp, mp, nvp) { + MNT_VNODE_FOREACH(xvp, mp, mvp) { VI_LOCK(xvp); MNT_IUNLOCK(mp); if ((xvp->v_iflag & VI_DOOMED) || @@ -506,6 +506,7 @@ loop: } if (vn_lock(xvp, LK_EXCLUSIVE | LK_INTERLOCK, td) != 0) { MNT_ILOCK(mp); + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto loop; } if (snapdebug) @@ -553,6 +554,7 @@ loop: free(copy_fs->fs_csp, M_UFSMNT); bawrite(sbp); sbp = NULL; + MNT_VNODE_FOREACH_ABORT(mp, mvp); goto out1; } MNT_ILOCK(mp); diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 04c4dba..c6c6510 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -445,7 +445,7 @@ ffs_cmount(struct mntarg *ma, void *data, int flags, struct thread *td) static int ffs_reload(struct mount *mp, struct thread *td) { - struct vnode *vp, *nvp, *devvp; + struct vnode *vp, *mvp, *devvp; struct inode *ip; void *space; struct buf *bp; @@ -536,7 +536,7 @@ ffs_reload(struct mount *mp, struct thread *td) loop: MNT_ILOCK(mp); - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); if (vp->v_iflag & VI_DOOMED) { VI_UNLOCK(vp); @@ -547,6 +547,7 @@ loop: * Step 4: invalidate all cached file data. */ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { + MNT_VNODE_FOREACH_ABORT(mp, mvp); goto loop; } if (vinvalbuf(vp, 0, td, 0, 0)) @@ -561,6 +562,7 @@ loop: if (error) { VOP_UNLOCK(vp, 0, td); vrele(vp); + MNT_VNODE_FOREACH_ABORT(mp, mvp); return (error); } ffs_load_inode(bp, ip, fs, ip->i_number); @@ -1106,7 +1108,7 @@ ffs_sync(mp, waitfor, td) int waitfor; struct thread *td; { - struct vnode *nvp, *vp, *devvp; + struct vnode *mvp, *vp, *devvp; struct inode *ip; struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs; @@ -1130,7 +1132,7 @@ ffs_sync(mp, waitfor, td) lockreq |= LK_INTERLOCK | LK_SLEEPFAIL; MNT_ILOCK(mp); loop: - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { /* * Depend on the mntvnode_slock to keep things stable enough * for a quick test. Since there might be hundreds of @@ -1152,8 +1154,10 @@ loop: MNT_IUNLOCK(mp); if ((error = vget(vp, lockreq, td)) != 0) { MNT_ILOCK(mp); - if (error == ENOENT || error == ENOLCK) + if (error == ENOENT || error == ENOLCK) { + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto loop; + } continue; } if ((error = ffs_syncvnode(vp, waitfor)) != 0) diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 2ba8d1a..f66c2eb 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -403,7 +403,7 @@ quotaon(td, mp, type, fname) { struct ufsmount *ump = VFSTOUFS(mp); struct vnode *vp, **vpp; - struct vnode *nvp; + struct vnode *mvp; struct dquot *dq; int error, flags; struct nameidata nd; @@ -453,11 +453,12 @@ quotaon(td, mp, type, fname) */ MNT_ILOCK(mp); again: - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); MNT_IUNLOCK(mp); if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { MNT_ILOCK(mp); + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto again; } if (vp->v_type == VNON || vp->v_writecount == 0) { @@ -470,8 +471,10 @@ again: VOP_UNLOCK(vp, 0, td); vrele(vp); MNT_ILOCK(mp); - if (error) + if (error) { + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); break; + } } MNT_IUNLOCK(mp); ump->um_qflags[type] &= ~QTF_OPENING; @@ -490,7 +493,7 @@ quotaoff(td, mp, type) int type; { struct vnode *vp; - struct vnode *qvp, *nvp; + struct vnode *qvp, *mvp; struct ufsmount *ump = VFSTOUFS(mp); struct dquot *dq; struct inode *ip; @@ -509,7 +512,7 @@ quotaoff(td, mp, type) */ MNT_ILOCK(mp); again: - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); MNT_IUNLOCK(mp); if (vp->v_type == VNON) { @@ -519,6 +522,7 @@ again: } if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { MNT_ILOCK(mp); + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto again; } ip = VTOI(vp); @@ -717,7 +721,7 @@ qsync(mp) { struct ufsmount *ump = VFSTOUFS(mp); struct thread *td = curthread; /* XXX */ - struct vnode *vp, *nvp; + struct vnode *vp, *mvp; struct dquot *dq; int i, error; @@ -736,7 +740,7 @@ qsync(mp) */ MNT_ILOCK(mp); again: - MNT_VNODE_FOREACH(vp, mp, nvp) { + MNT_VNODE_FOREACH(vp, mp, mvp) { VI_LOCK(vp); MNT_IUNLOCK(mp); if (vp->v_type == VNON) { @@ -747,8 +751,10 @@ again: error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td); if (error) { MNT_ILOCK(mp); - if (error == ENOENT) + if (error == ENOENT) { + MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp); goto again; + } continue; } for (i = 0; i < MAXQUOTAS; i++) { diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c index b6c0901..3b13ccc 100644 --- a/usr.bin/fstat/fstat.c +++ b/usr.bin/fstat/fstat.c @@ -692,6 +692,7 @@ nfs_filestat(struct vnode *vp, struct filestat *fsp) break; case VNON: case VBAD: + case VMARKER: return 0; }; fsp->mode = mode; |