diff options
author | kib <kib@FreeBSD.org> | 2009-06-30 10:07:00 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2009-06-30 10:07:00 +0000 |
commit | c424611d793944a4fe03022da72a5ecc34649c72 (patch) | |
tree | d14f883c5b9a0d85635c462dd9fd2f1f1a9cefdc /sys/ufs/ffs | |
parent | 905d9397a05effde536c6c52c272bcd0bd3ccfd5 (diff) | |
download | FreeBSD-src-c424611d793944a4fe03022da72a5ecc34649c72.zip FreeBSD-src-c424611d793944a4fe03022da72a5ecc34649c72.tar.gz |
Softdep_fsync() may need to lock parent directory of the synced vnode.
Use inlined (due to FFSV_FORCEINSMQ) version of vn_vget_ino() to prevent
mountpoint from being unmounted and freed while no vnodes are locked.
Tested by: pho
Approved by: re (kensmith)
MFC after: 1 month
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 195df44..d7b8818 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -5102,10 +5102,28 @@ softdep_fsync(vp) FREE_LOCK(&lk); if (ffs_vgetf(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp, FFSV_FORCEINSMQ)) { + error = vfs_busy(mp, MBF_NOWAIT); + if (error != 0) { + VOP_UNLOCK(vp, 0); + error = vfs_busy(mp, 0); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (error != 0) + return (ENOENT); + if (vp->v_iflag & VI_DOOMED) { + vfs_unbusy(mp); + return (ENOENT); + } + } VOP_UNLOCK(vp, 0); error = ffs_vgetf(mp, parentino, LK_EXCLUSIVE, &pvp, FFSV_FORCEINSMQ); + vfs_unbusy(mp); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (vp->v_iflag & VI_DOOMED) { + if (error == 0) + vput(pvp); + error = ENOENT; + } if (error != 0) return (error); } |