diff options
author | jeff <jeff@FreeBSD.org> | 2003-10-04 14:25:45 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2003-10-04 14:25:45 +0000 |
commit | c960cfdda5f812eabc7623c6b460785856f3346c (patch) | |
tree | d3ac50bdc714a7915147012dd4c8924a2d8e3f6a /sys/ufs | |
parent | 25821dd99f26f818539e18967bd966b06a09740a (diff) | |
download | FreeBSD-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.c | 20 |
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; } /* |