Fix some locking cases where we ask for exclusively locked vnode, but we get
shared locked vnode in instead when vfs.lookup_shared is set to 1. Discussed with: kib, kris Tested by: kris Approved by: re (kensmith)
This commit is contained in:
parent
e84091cb52
commit
b4d7e2983c
@ -314,6 +314,7 @@ cache_lookup(dvp, vpp, cnp)
|
||||
struct componentname *cnp;
|
||||
{
|
||||
struct namecache *ncp;
|
||||
struct thread *td;
|
||||
u_int32_t hash;
|
||||
int error, ltype;
|
||||
|
||||
@ -321,6 +322,7 @@ cache_lookup(dvp, vpp, cnp)
|
||||
cnp->cn_flags &= ~MAKEENTRY;
|
||||
return (0);
|
||||
}
|
||||
td = cnp->cn_thread;
|
||||
retry:
|
||||
CACHE_LOCK();
|
||||
numcalls++;
|
||||
@ -419,18 +421,29 @@ cache_lookup(dvp, vpp, cnp)
|
||||
if (dvp == *vpp) { /* lookup on "." */
|
||||
VREF(*vpp);
|
||||
CACHE_UNLOCK();
|
||||
/*
|
||||
* When we lookup "." we still can be asked to lock it
|
||||
* differently...
|
||||
*/
|
||||
ltype = cnp->cn_lkflags & (LK_SHARED | LK_EXCLUSIVE);
|
||||
if (ltype == VOP_ISLOCKED(*vpp, td))
|
||||
return (-1);
|
||||
else if (ltype == LK_EXCLUSIVE)
|
||||
vn_lock(*vpp, LK_UPGRADE | LK_RETRY, td);
|
||||
return (-1);
|
||||
}
|
||||
ltype = 0; /* silence gcc warning */
|
||||
if (cnp->cn_flags & ISDOTDOT) {
|
||||
ltype = VOP_ISLOCKED(dvp, cnp->cn_thread);
|
||||
VOP_UNLOCK(dvp, 0, cnp->cn_thread);
|
||||
ltype = VOP_ISLOCKED(dvp, td);
|
||||
VOP_UNLOCK(dvp, 0, td);
|
||||
}
|
||||
VI_LOCK(*vpp);
|
||||
CACHE_UNLOCK();
|
||||
error = vget(*vpp, cnp->cn_lkflags | LK_INTERLOCK, cnp->cn_thread);
|
||||
error = vget(*vpp, cnp->cn_lkflags | LK_INTERLOCK, td);
|
||||
if (cnp->cn_flags & ISDOTDOT)
|
||||
vn_lock(dvp, ltype | LK_RETRY, cnp->cn_thread);
|
||||
vn_lock(dvp, ltype | LK_RETRY, td);
|
||||
if ((cnp->cn_flags & ISLASTCN) && (cnp->cn_lkflags & LK_EXCLUSIVE))
|
||||
ASSERT_VOP_ELOCKED(*vpp, "cache_lookup");
|
||||
if (error) {
|
||||
*vpp = NULL;
|
||||
goto retry;
|
||||
|
@ -772,6 +772,14 @@ lookup(struct nameidata *ndp)
|
||||
if ((cnp->cn_flags & LOCKLEAF) == 0)
|
||||
VOP_UNLOCK(dp, 0, td);
|
||||
success:
|
||||
/*
|
||||
* Because of lookup_shared we may have the vnode shared locked, but
|
||||
* the caller may want it to be exclusively locked.
|
||||
*/
|
||||
if ((cnp->cn_flags & (ISLASTCN | LOCKSHARED | LOCKLEAF)) ==
|
||||
(ISLASTCN | LOCKLEAF) && VOP_ISLOCKED(dp, td) != LK_EXCLUSIVE) {
|
||||
vn_lock(dp, LK_UPGRADE | LK_RETRY, td);
|
||||
}
|
||||
if (vfslocked && dvfslocked)
|
||||
VFS_UNLOCK_GIANT(dvfslocked); /* Only need one */
|
||||
if (vfslocked || dvfslocked)
|
||||
|
Loading…
Reference in New Issue
Block a user