diff options
author | jhb <jhb@FreeBSD.org> | 2001-06-28 04:12:56 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-06-28 04:12:56 +0000 |
commit | 822af43e20c60c75b37a74c16f87f16578ec5250 (patch) | |
tree | 675b39c84e554e1faba591f95ea66dfe13137df4 | |
parent | ab91beada7d88e4a56b4217fee5826cb97b5cef7 (diff) | |
download | FreeBSD-src-822af43e20c60c75b37a74c16f87f16578ec5250.zip FreeBSD-src-822af43e20c60c75b37a74c16f87f16578ec5250.tar.gz |
- Fix a mntvnode and vnode interlock reversal.
- Protect the mnt_vnode list with the mntvnode lock.
- Use queue(9) macros.
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 12 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_quota.c | 53 |
2 files changed, 46 insertions, 19 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 30bd592..e99bef3 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -490,8 +490,8 @@ loop: /* * Step 5: invalidate all cached file data. */ - mtx_lock(&vp->v_interlock); mtx_unlock(&mntvnode_mtx); + mtx_lock(&vp->v_interlock); if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) { goto loop; } @@ -1013,17 +1013,19 @@ loop: */ if (vp->v_mount != mp) goto loop; - mtx_lock(&vp->v_interlock); nvp = LIST_NEXT(vp, v_mntvnodes); + + mtx_unlock(&mntvnode_mtx); + mtx_lock(&vp->v_interlock); ip = VTOI(vp); if (vp->v_type == VNON || ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && TAILQ_EMPTY(&vp->v_dirtyblkhd))) { mtx_unlock(&vp->v_interlock); + mtx_lock(&mntvnode_mtx); continue; } if (vp->v_type != VCHR) { - mtx_unlock(&mntvnode_mtx); if ((error = vget(vp, lockreq, p)) != 0) { mtx_lock(&mntvnode_mtx); if (error == ENOENT) @@ -1034,13 +1036,11 @@ loop: allerror = error; VOP_UNLOCK(vp, 0, p); vrele(vp); - mtx_lock(&mntvnode_mtx); } else { - mtx_unlock(&mntvnode_mtx); mtx_unlock(&vp->v_interlock); UFS_UPDATE(vp, wait); - mtx_lock(&mntvnode_mtx); } + mtx_lock(&mntvnode_mtx); } mtx_unlock(&mntvnode_mtx); /* diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 1b76759..6992160 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -438,22 +438,33 @@ quotaon(p, mp, type, fname) * adding references to quota file being opened. * NB: only need to add dquot's for inodes being modified. */ + mtx_lock(&mntvnode_mtx); again: for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nextvp) { + if (vp->v_mount != mp) + goto again; nextvp = LIST_NEXT(vp, v_mntvnodes); - if (vp->v_type == VNON || vp->v_writecount == 0) + + mtx_unlock(&mntvnode_mtx); + mtx_lock(&vp->v_interlock); + if (vp->v_type == VNON || vp->v_writecount == 0) { + 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 again; - error = getinoquota(VTOI(vp)); - if (error) { - vput(vp); - break; } + error = getinoquota(VTOI(vp)); vput(vp); - if (LIST_NEXT(vp, v_mntvnodes) != nextvp || vp->v_mount != mp) + mtx_lock(&mntvnode_mtx); + if (error) + break; + if (LIST_NEXT(vp, v_mntvnodes) != nextvp) goto again; } + mtx_unlock(&mntvnode_mtx); ump->um_qflags[type] &= ~QTF_OPENING; if (error) quotaoff(p, mp, type); @@ -483,21 +494,34 @@ quotaoff(p, mp, type) * Search vnodes associated with this mount point, * deleting any references to quota file being closed. */ + mtx_lock(&mntvnode_mtx); again: for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nextvp) { + if (vp->v_mount != mp) + goto again; nextvp = LIST_NEXT(vp, v_mntvnodes); - if (vp->v_type == VNON) + + mtx_unlock(&mntvnode_mtx); + mtx_lock(&vp->v_interlock); + if (vp->v_type == VNON) { + 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 again; + } ip = VTOI(vp); dq = ip->i_dquot[type]; ip->i_dquot[type] = NODQUOT; dqrele(vp, dq); vput(vp); - if (LIST_NEXT(vp, v_mntvnodes) != nextvp || vp->v_mount != mp) + mtx_lock(&mntvnode_mtx); + if (LIST_NEXT(vp, v_mntvnodes) != nextvp) goto again; } + mtx_unlock(&mntvnode_mtx); dqflush(qvp); qvp->v_flag &= ~VSYSTEM; error = vn_close(qvp, FREAD|FWRITE, p->p_ucred, p); @@ -675,10 +699,13 @@ again: if (vp->v_mount != mp) goto again; nextvp = LIST_NEXT(vp, v_mntvnodes); - if (vp->v_type == VNON) - continue; - mtx_lock(&vp->v_interlock); mtx_unlock(&mntvnode_mtx); + mtx_lock(&vp->v_interlock); + if (vp->v_type == VNON) { + mtx_unlock(&vp->v_interlock); + mtx_lock(&mntvnode_mtx); + continue; + } error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p); if (error) { mtx_lock(&mntvnode_mtx); |