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:
parent
b4cf0e62f4
commit
11c68fb23f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=185170
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user