summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2003-10-04 14:25:45 +0000
committerjeff <jeff@FreeBSD.org>2003-10-04 14:25:45 +0000
commitc960cfdda5f812eabc7623c6b460785856f3346c (patch)
treed3ac50bdc714a7915147012dd4c8924a2d8e3f6a /sys/ufs
parent25821dd99f26f818539e18967bd966b06a09740a (diff)
downloadFreeBSD-src-c960cfdda5f812eabc7623c6b460785856f3346c.zip
FreeBSD-src-c960cfdda5f812eabc7623c6b460785856f3346c.tar.gz
- Fix an unlocked call to GETATTR by slightly shuffling the code in
ffs_snapshot() around. - Acquire the interlock before releasing the mntvnode_mtx. Use the interlock to protect v_usecount access.
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index 446f63c..a4a9fe3 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -415,22 +415,30 @@ loop:
if (xvp->v_mount != mp)
goto loop;
nvp = TAILQ_NEXT(xvp, v_nmntvnodes);
+ VI_LOCK(xvp);
mtx_unlock(&mntvnode_mtx);
- mp_fixme("Unlocked GETATTR.");
- if (vrefcnt(xvp) == 0 || xvp->v_type == VNON ||
- (VTOI(xvp)->i_flags & SF_SNAPSHOT) ||
- (VOP_GETATTR(xvp, &vat, td->td_ucred, td) == 0 &&
- vat.va_nlink > 0)) {
+ if (xvp->v_usecount == 0 || xvp->v_type == VNON ||
+ (VTOI(xvp)->i_flags & SF_SNAPSHOT)) {
+ VI_UNLOCK(xvp);
mtx_lock(&mntvnode_mtx);
continue;
}
if (snapdebug)
vprint("ffs_snapshot: busy vnode", xvp);
- if (vn_lock(xvp, LK_EXCLUSIVE, td) != 0)
+ if (vn_lock(xvp, LK_EXCLUSIVE | LK_INTERLOCK, td) != 0) {
+ mtx_lock(&mntvnode_mtx);
goto loop;
+ }
+ if (VOP_GETATTR(xvp, &vat, td->td_ucred, td) == 0 &&
+ vat.va_nlink > 0) {
+ VOP_UNLOCK(xvp, 0, td);
+ mtx_lock(&mntvnode_mtx);
+ continue;
+ }
xp = VTOI(xvp);
if (ffs_checkfreefile(copy_fs, vp, xp->i_number)) {
VOP_UNLOCK(xvp, 0, td);
+ mtx_lock(&mntvnode_mtx);
continue;
}
/*
OpenPOWER on IntegriCloud