Add MNTK_LOOKUP_EXCL_DOTDOT struct mount flag, which specifies to the
lookup code that dotdot lookups shall override any shared lock requests with the exclusive one. The flag is useful for filesystems which sometimes need to upgrade shared lock to exclusive inside the VOP_LOOKUP or later, which cannot be done safely for dotdot, due to dvp also locked and causing LOR. In collaboration with: pho MFC after: 3 weeks
This commit is contained in:
parent
7ea73aa912
commit
01b848f0ee
@ -406,11 +406,13 @@ namei(struct nameidata *ndp)
|
||||
}
|
||||
|
||||
static int
|
||||
compute_cn_lkflags(struct mount *mp, int lkflags)
|
||||
compute_cn_lkflags(struct mount *mp, int lkflags, int cnflags)
|
||||
{
|
||||
|
||||
if (mp == NULL ||
|
||||
((lkflags & LK_SHARED) && !(mp->mnt_kern_flag & MNTK_LOOKUP_SHARED))) {
|
||||
if (mp == NULL || ((lkflags & LK_SHARED) &&
|
||||
(!(mp->mnt_kern_flag & MNTK_LOOKUP_SHARED) ||
|
||||
((cnflags & ISDOTDOT) &&
|
||||
(mp->mnt_kern_flag & MNTK_LOOKUP_EXCL_DOTDOT))))) {
|
||||
lkflags &= ~LK_SHARED;
|
||||
lkflags |= LK_EXCLUSIVE;
|
||||
}
|
||||
@ -539,7 +541,8 @@ lookup(struct nameidata *ndp)
|
||||
dp = ndp->ni_startdir;
|
||||
ndp->ni_startdir = NULLVP;
|
||||
vn_lock(dp,
|
||||
compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags | LK_RETRY));
|
||||
compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags | LK_RETRY,
|
||||
cnp->cn_flags));
|
||||
|
||||
dirloop:
|
||||
/*
|
||||
@ -700,7 +703,7 @@ lookup(struct nameidata *ndp)
|
||||
VFS_UNLOCK_GIANT(tvfslocked);
|
||||
vn_lock(dp,
|
||||
compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags |
|
||||
LK_RETRY));
|
||||
LK_RETRY, ISDOTDOT));
|
||||
}
|
||||
}
|
||||
|
||||
@ -738,7 +741,8 @@ lookup(struct nameidata *ndp)
|
||||
vprint("lookup in", dp);
|
||||
#endif
|
||||
lkflags_save = cnp->cn_lkflags;
|
||||
cnp->cn_lkflags = compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags);
|
||||
cnp->cn_lkflags = compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags,
|
||||
cnp->cn_flags);
|
||||
if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) {
|
||||
cnp->cn_lkflags = lkflags_save;
|
||||
KASSERT(ndp->ni_vp == NULL, ("leaf should be empty"));
|
||||
@ -757,7 +761,7 @@ lookup(struct nameidata *ndp)
|
||||
VFS_UNLOCK_GIANT(tvfslocked);
|
||||
vn_lock(dp,
|
||||
compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags |
|
||||
LK_RETRY));
|
||||
LK_RETRY, cnp->cn_flags));
|
||||
goto unionlookup;
|
||||
}
|
||||
|
||||
@ -829,8 +833,8 @@ lookup(struct nameidata *ndp)
|
||||
dvfslocked = 0;
|
||||
vref(vp_crossmp);
|
||||
ndp->ni_dvp = vp_crossmp;
|
||||
error = VFS_ROOT(mp, compute_cn_lkflags(mp, cnp->cn_lkflags),
|
||||
&tdp);
|
||||
error = VFS_ROOT(mp, compute_cn_lkflags(mp, cnp->cn_lkflags,
|
||||
cnp->cn_flags), &tdp);
|
||||
vfs_unbusy(mp);
|
||||
if (vn_lock(vp_crossmp, LK_SHARED | LK_NOWAIT))
|
||||
panic("vp_crossmp exclusively locked or reclaimed");
|
||||
|
@ -373,6 +373,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
|
||||
#define MNTK_NO_IOPF 0x00000100 /* Disallow page faults during reads
|
||||
and writes. Filesystem shall properly
|
||||
handle i/o state on EFAULT. */
|
||||
#define MNTK_LOOKUP_EXCL_DOTDOT 0x00000800
|
||||
#define MNTK_NOASYNC 0x00800000 /* disable async */
|
||||
#define MNTK_UNMOUNT 0x01000000 /* unmount in progress */
|
||||
#define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */
|
||||
|
Loading…
Reference in New Issue
Block a user