- Lock access to the buf lists.
- Use vrefcnt() where appropriate. - Add some locking asserts.
This commit is contained in:
parent
906daccf72
commit
5c7f8a426d
@ -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");
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user