Avoid double-unlock or double unreference for ndp->ni_dvp when the vnode dp
lock upgrade right after the 'success' label fails. In collaboration with: pho MFC after: 1 week
This commit is contained in:
parent
f8f33f6ab6
commit
cdb7a43117
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=229185
@ -508,12 +508,14 @@ lookup(struct nameidata *ndp)
|
||||
int dvfslocked; /* VFS Giant state for parent */
|
||||
int tvfslocked;
|
||||
int lkflags_save;
|
||||
int ni_dvp_unlocked;
|
||||
|
||||
/*
|
||||
* Setup: break out flag bits into variables.
|
||||
*/
|
||||
dvfslocked = (ndp->ni_cnd.cn_flags & GIANTHELD) != 0;
|
||||
vfslocked = 0;
|
||||
ni_dvp_unlocked = 0;
|
||||
ndp->ni_cnd.cn_flags &= ~GIANTHELD;
|
||||
wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
|
||||
KASSERT(cnp->cn_nameiop == LOOKUP || wantparent,
|
||||
@ -861,8 +863,10 @@ lookup(struct nameidata *ndp)
|
||||
/*
|
||||
* Symlink code always expects an unlocked dvp.
|
||||
*/
|
||||
if (ndp->ni_dvp != ndp->ni_vp)
|
||||
if (ndp->ni_dvp != ndp->ni_vp) {
|
||||
VOP_UNLOCK(ndp->ni_dvp, 0);
|
||||
ni_dvp_unlocked = 1;
|
||||
}
|
||||
goto success;
|
||||
}
|
||||
|
||||
@ -909,14 +913,17 @@ lookup(struct nameidata *ndp)
|
||||
VREF(ndp->ni_startdir);
|
||||
}
|
||||
if (!wantparent) {
|
||||
ni_dvp_unlocked = 2;
|
||||
if (ndp->ni_dvp != dp)
|
||||
vput(ndp->ni_dvp);
|
||||
else
|
||||
vrele(ndp->ni_dvp);
|
||||
VFS_UNLOCK_GIANT(dvfslocked);
|
||||
dvfslocked = 0;
|
||||
} else if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp != dp)
|
||||
} else if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp != dp) {
|
||||
VOP_UNLOCK(ndp->ni_dvp, 0);
|
||||
ni_dvp_unlocked = 1;
|
||||
}
|
||||
|
||||
if (cnp->cn_flags & AUDITVNODE1)
|
||||
AUDIT_ARG_VNODE1(dp);
|
||||
@ -945,10 +952,12 @@ lookup(struct nameidata *ndp)
|
||||
return (0);
|
||||
|
||||
bad2:
|
||||
if (dp != ndp->ni_dvp)
|
||||
vput(ndp->ni_dvp);
|
||||
else
|
||||
vrele(ndp->ni_dvp);
|
||||
if (ni_dvp_unlocked != 2) {
|
||||
if (dp != ndp->ni_dvp && !ni_dvp_unlocked)
|
||||
vput(ndp->ni_dvp);
|
||||
else
|
||||
vrele(ndp->ni_dvp);
|
||||
}
|
||||
bad:
|
||||
if (!dpunlocked)
|
||||
vput(dp);
|
||||
|
Loading…
Reference in New Issue
Block a user