1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-17 15:27:36 +00:00

Busy ufs filesystem around block of code that does ".." lookup. Since

mnt_lock is before lock of any vnode on the mp, it uses LK_NOWAIT. Since
MNTK_UNMOUNT may be transient, pdp lock is dropped when vfs_busy()
failed, and operation is retried after some time. This way, ffs_vget()
is not called on the mp that may be in the process of being destroyed by
unmount.

Check for the VI_DOOMED flag on pdp after its lock is reacquired, to
better detect some situations where directory containing ".."
entry is removed during the lookup.

Reviewed by:	tegge, attilio (previous version)
Tested by:	pho
MFC after:	1 month
This commit is contained in:
Konstantin Belousov 2008-11-22 13:11:11 +00:00
parent b4cf0e62f4
commit 11c68fb23f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=185170

View File

@ -157,6 +157,8 @@ ufs_lookup(ap)
int nameiop = cnp->cn_nameiop;
ino_t ino;
int ltype;
int pdoomed;
struct mount *mp;
bp = NULL;
slotoffset = -1;
@ -578,9 +580,32 @@ ufs_lookup(ap)
pdp = vdp;
if (flags & ISDOTDOT) {
ltype = VOP_ISLOCKED(pdp);
mp = pdp->v_mount;
for (;;) {
error = vfs_busy(mp, MBF_NOWAIT);
if (error == 0)
break;
VOP_UNLOCK(pdp, 0);
pause("ufs_dd", 1);
vn_lock(pdp, ltype | LK_RETRY);
VI_LOCK(pdp);
pdoomed = pdp->v_iflag & VI_DOOMED;
VI_UNLOCK(pdp);
if (pdoomed)
return (ENOENT);
}
VOP_UNLOCK(pdp, 0); /* race to get the inode */
error = VFS_VGET(pdp->v_mount, ino, cnp->cn_lkflags, &tdp);
error = VFS_VGET(mp, ino, cnp->cn_lkflags, &tdp);
vfs_unbusy(mp);
vn_lock(pdp, ltype | LK_RETRY);
VI_LOCK(pdp);
pdoomed = pdp->v_iflag & VI_DOOMED;
VI_UNLOCK(pdp);
if (pdoomed) {
if (error == 0)
vput(tdp);
error = ENOENT;
}
if (error)
return (error);
*vpp = tdp;