diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c index d8243ae917dc..f88b04c85dda 100644 --- a/sys/nfsclient/nfs_bio.c +++ b/sys/nfsclient/nfs_bio.c @@ -1344,7 +1344,7 @@ nfs_doio(struct buf *bp, struct ucred *cr, struct thread *td) uiop->uio_resid = 0; } } - mp_fixme("Accessing VV_TEXT without a lock."); + ASSERT_VOP_LOCKED(vp, "nfs_doio"); if (p && (vp->v_vflag & VV_TEXT) && (np->n_mtime != np->n_vattr.va_mtime.tv_sec)) { uprintf("Process killed due to text file modification\n"); diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c index 90ef7aa40d34..34729a318022 100644 --- a/sys/nfsclient/nfs_node.c +++ b/sys/nfsclient/nfs_node.c @@ -281,7 +281,7 @@ nfs_inactive(struct vop_inactive_args *ap) struct thread *td = curthread; /* XXX */ np = VTONFS(ap->a_vp); - if (prtactive && ap->a_vp->v_usecount != 0) + if (prtactive && vrefcnt(ap->a_vp) != 0) vprint("nfs_inactive: pushing active", ap->a_vp); if (ap->a_vp->v_type != VDIR) { sp = np->n_sillyrename; @@ -296,7 +296,7 @@ nfs_inactive(struct vop_inactive_args *ap) * are being forcibly unmounted in which case we already * have our own reference. */ - if (ap->a_vp->v_usecount > 0) + if (vrefcnt(ap->a_vp) > 0) (void) nfs_vinvalbuf(ap->a_vp, 0, sp->s_cred, td, 1); else if (vget(ap->a_vp, 0, td)) panic("nfs_inactive: lost vnode"); @@ -327,7 +327,7 @@ nfs_reclaim(struct vop_reclaim_args *ap) struct nfsnode *np = VTONFS(vp); struct nfsdmap *dp, *dp2; - if (prtactive && vp->v_usecount != 0) + if (prtactive && vrefcnt(vp) != 0) vprint("nfs_reclaim: pushing active", vp); if (np->n_hash.le_prev != NULL) /* XXX beware */ diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c index 130512254a98..c88f51e0501c 100644 --- a/sys/nfsclient/nfs_subs.c +++ b/sys/nfsclient/nfs_subs.c @@ -793,6 +793,8 @@ nfs_clearcommit(struct mount *mp) if (vp->v_mount != mp) /* Paranoia */ goto loop; nvp = TAILQ_NEXT(vp, v_nmntvnodes); + VI_LOCK(vp); + mtx_unlock(&mntvnode_mtx); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { nbp = TAILQ_NEXT(bp, b_vnbufs); if (BUF_REFCNT(bp) == 0 && @@ -800,6 +802,8 @@ nfs_clearcommit(struct mount *mp) == (B_DELWRI | B_NEEDCOMMIT)) bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK); } + VI_UNLOCK(vp); + mtx_lock(&mntvnode_mtx); } mtx_unlock(&mntvnode_mtx); splx(s); diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index f4a083d8ec5b..04deade983b4 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -980,10 +980,10 @@ nfs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct thread *td) goto loop; vnp = TAILQ_NEXT(vp, v_nmntvnodes); mtx_unlock(&mntvnode_mtx); - mtx_lock(&vp->v_interlock); + VI_LOCK(vp); if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) || waitfor == MNT_LAZY) { - mtx_unlock(&vp->v_interlock); + VI_UNLOCK(vp); mtx_lock(&mntvnode_mtx); continue; } diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index e55eb00614b4..dff0baa80d15 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -1419,12 +1419,12 @@ nfs_remove(struct vop_remove_args *ap) #ifndef DIAGNOSTIC if ((cnp->cn_flags & HASBUF) == 0) panic("nfs_remove: no name"); - if (vp->v_usecount < 1) + if (vrefcnt(vp) < 1) panic("nfs_remove: bad v_usecount"); #endif if (vp->v_type == VDIR) error = EPERM; - else if (vp->v_usecount == 1 || (np->n_sillyrename && + else if (vrefcnt(vp) == 1 || (np->n_sillyrename && VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_thread) == 0 && vattr.va_nlink > 1)) { /* @@ -1543,7 +1543,7 @@ nfs_rename(struct vop_rename_args *ap) * rename of the new file over it. * XXX Can't sillyrename a directory. */ - if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && + if (tvp && vrefcnt(tvp) > 1 && !VTONFS(tvp)->n_sillyrename && tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { vput(tvp); tvp = NULL; @@ -2616,6 +2616,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, * Count up how many buffers waiting for a commit. */ bveccount = 0; + VI_LOCK(vp); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { nbp = TAILQ_NEXT(bp, b_vnbufs); if (BUF_REFCNT(bp) == 0 && @@ -2645,13 +2646,16 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, bvecsize = NFS_COMMITBVECSIZ; } for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { - nbp = TAILQ_NEXT(bp, b_vnbufs); if (bvecpos >= bvecsize) break; + VI_UNLOCK(vp); if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) != (B_DELWRI | B_NEEDCOMMIT) || - BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) + BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) { + VI_LOCK(vp); + nbp = TAILQ_NEXT(bp, b_vnbufs); continue; + } bremfree(bp); /* * Work out if all buffers are using the same cred @@ -2671,6 +2675,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, bp->b_flags |= B_WRITEINPROG; vfs_busy_pages(bp, 1); + VI_LOCK(vp); /* * bp is protected by being locked, but nbp is not * and vfs_busy_pages() may sleep. We have to @@ -2695,6 +2700,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, endoff = toff; } splx(s); + VI_UNLOCK(vp); } if (bvecpos > 0) { /* @@ -2747,7 +2753,9 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, * into bundirty(). XXX */ s = splbio(); + VI_LOCK(vp); vp->v_numoutput++; + VI_UNLOCK(vp); bp->b_flags |= B_ASYNC; bundirty(bp); bp->b_flags &= ~B_DONE; @@ -2764,11 +2772,15 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, */ loop: s = splbio(); + VI_LOCK(vp); for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { nbp = TAILQ_NEXT(bp, b_vnbufs); + VI_UNLOCK(vp); if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) { - if (waitfor != MNT_WAIT || passone) + if (waitfor != MNT_WAIT || passone) { + VI_LOCK(vp); continue; + } error = BUF_TIMELOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL, "nfsfsync", slpflag, slptimeo); splx(s); @@ -2790,6 +2802,7 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, panic("nfs_fsync: not dirty"); if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) { BUF_UNLOCK(bp); + VI_LOCK(vp); continue; } bremfree(bp); @@ -2804,10 +2817,10 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, splx(s); if (passone) { passone = 0; + VI_UNLOCK(vp); goto again; } if (waitfor == MNT_WAIT) { - VI_LOCK(vp); while (vp->v_numoutput) { vp->v_iflag |= VI_BWAIT; error = msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp), @@ -2824,11 +2837,12 @@ nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td, } } } - VI_UNLOCK(vp); if (!TAILQ_EMPTY(&vp->v_dirtyblkhd) && commit) { + VI_UNLOCK(vp); goto loop; } } + VI_UNLOCK(vp); if (np->n_flag & NWRITEERR) { error = np->n_error; np->n_flag &= ~NWRITEERR; @@ -2907,7 +2921,9 @@ nfs_writebp(struct buf *bp, int force, struct thread *td) bp->b_ioflags &= ~BIO_ERROR; bp->b_iocmd = BIO_WRITE; + VI_LOCK(bp->b_vp); bp->b_vp->v_numoutput++; + VI_UNLOCK(bp->b_vp); curthread->td_proc->p_stats->p_ru.ru_oublock++; splx(s); @@ -3045,7 +3061,7 @@ nfsspec_close(struct vop_close_args *ap) if (np->n_flag & (NACC | NUPD)) { np->n_flag |= NCHG; - if (vp->v_usecount == 1 && + if (vrefcnt(vp) == 1 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { VATTR_NULL(&vattr); if (np->n_flag & NACC) @@ -3110,7 +3126,7 @@ nfsfifo_close(struct vop_close_args *ap) if (np->n_flag & NUPD) np->n_mtim = ts; np->n_flag |= NCHG; - if (vp->v_usecount == 1 && + if (vrefcnt(vp) == 1 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { VATTR_NULL(&vattr); if (np->n_flag & NACC)