summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-06-28 04:12:56 +0000
committerjhb <jhb@FreeBSD.org>2001-06-28 04:12:56 +0000
commit822af43e20c60c75b37a74c16f87f16578ec5250 (patch)
tree675b39c84e554e1faba591f95ea66dfe13137df4
parentab91beada7d88e4a56b4217fee5826cb97b5cef7 (diff)
downloadFreeBSD-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.c12
-rw-r--r--sys/ufs/ufs/ufs_quota.c53
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);
OpenPOWER on IntegriCloud