mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-16 10:20:30 +00:00
- Move the logic that locks and refs the new vnode from vfs_cache_lookup()
to cache_lookup(). This allows us to acquire the vnode interlock before dropping the cache lock. This protects the vnodes identity until we have locked it. Sponsored by: Isilon Systems, Inc.
This commit is contained in:
parent
b6a9d20adc
commit
5280e61f2f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=144296
@ -328,6 +328,10 @@ cache_leaf_test(struct vnode *vp)
|
||||
* returned. If the lookup determines that the name does not exist
|
||||
* (negative cacheing), a status of ENOENT is returned. If the lookup
|
||||
* fails, a status of zero is returned.
|
||||
*
|
||||
* vpp is locked and ref'd on return. If we're looking up DOTDOT, dvp is
|
||||
* unlocked. If we're looking up . an extra ref is taken, but the lock is
|
||||
* not recursively acquired.
|
||||
*/
|
||||
|
||||
int
|
||||
@ -343,7 +347,7 @@ cache_lookup(dvp, vpp, cnp)
|
||||
cnp->cn_flags &= ~MAKEENTRY;
|
||||
return (0);
|
||||
}
|
||||
|
||||
retry:
|
||||
CACHE_LOCK();
|
||||
numcalls++;
|
||||
|
||||
@ -351,8 +355,7 @@ cache_lookup(dvp, vpp, cnp)
|
||||
if (cnp->cn_namelen == 1) {
|
||||
*vpp = dvp;
|
||||
dothits++;
|
||||
CACHE_UNLOCK();
|
||||
return (-1);
|
||||
goto success;
|
||||
}
|
||||
if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
|
||||
dotdothits++;
|
||||
@ -363,8 +366,7 @@ cache_lookup(dvp, vpp, cnp)
|
||||
return (0);
|
||||
}
|
||||
*vpp = dvp->v_dd;
|
||||
CACHE_UNLOCK();
|
||||
return (-1);
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,8 +405,7 @@ cache_lookup(dvp, vpp, cnp)
|
||||
numposhits++;
|
||||
nchstats.ncs_goodhits++;
|
||||
*vpp = ncp->nc_vp;
|
||||
CACHE_UNLOCK();
|
||||
return (-1);
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* We found a negative match, and want to create it, so purge */
|
||||
@ -430,6 +431,28 @@ cache_lookup(dvp, vpp, cnp)
|
||||
cnp->cn_flags |= ISWHITEOUT;
|
||||
CACHE_UNLOCK();
|
||||
return (ENOENT);
|
||||
|
||||
success:
|
||||
/*
|
||||
* On success we return a locked and ref'd vnode as per the lookup
|
||||
* protocol.
|
||||
*/
|
||||
if (dvp == *vpp) { /* lookup on "." */
|
||||
VREF(*vpp);
|
||||
CACHE_UNLOCK();
|
||||
return (-1);
|
||||
}
|
||||
if (cnp->cn_flags & ISDOTDOT)
|
||||
VOP_UNLOCK(dvp, 0, cnp->cn_thread);
|
||||
VI_LOCK(*vpp);
|
||||
CACHE_UNLOCK();
|
||||
if (vget(*vpp, cnp->cn_lkflags | LK_INTERLOCK, cnp->cn_thread)) {
|
||||
if (cnp->cn_flags & ISDOTDOT)
|
||||
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, cnp->cn_thread);
|
||||
*vpp = NULL;
|
||||
goto retry;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -632,14 +655,13 @@ vfs_cache_lookup(ap)
|
||||
struct componentname *a_cnp;
|
||||
} */ *ap;
|
||||
{
|
||||
struct vnode *dvp, *vp;
|
||||
struct vnode *dvp;
|
||||
int error;
|
||||
struct vnode **vpp = ap->a_vpp;
|
||||
struct componentname *cnp = ap->a_cnp;
|
||||
struct ucred *cred = cnp->cn_cred;
|
||||
int flags = cnp->cn_flags;
|
||||
struct thread *td = cnp->cn_thread;
|
||||
u_long vpid; /* capability number of vnode */
|
||||
|
||||
*vpp = NULL;
|
||||
dvp = ap->a_dvp;
|
||||
@ -652,39 +674,15 @@ vfs_cache_lookup(ap)
|
||||
return (EROFS);
|
||||
|
||||
error = VOP_ACCESS(dvp, VEXEC, cred, td);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = cache_lookup(dvp, vpp, cnp);
|
||||
if (!error)
|
||||
if (error == 0)
|
||||
return (VOP_CACHEDLOOKUP(dvp, vpp, cnp));
|
||||
if (error == ENOENT)
|
||||
return (error);
|
||||
vp = *vpp;
|
||||
vpid = vp->v_id;
|
||||
if (dvp == vp) { /* lookup on "." */
|
||||
VREF(vp);
|
||||
error = 0;
|
||||
} else if (flags & ISDOTDOT) {
|
||||
VOP_UNLOCK(dvp, 0, td);
|
||||
error = vget(vp, cnp->cn_lkflags, td);
|
||||
if (error)
|
||||
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||
} else
|
||||
error = vget(vp, cnp->cn_lkflags, td);
|
||||
/*
|
||||
* Check that the capability number did not change
|
||||
* while we were waiting for the lock.
|
||||
*/
|
||||
if (!error) {
|
||||
if (vpid == vp->v_id)
|
||||
return (0);
|
||||
vput(vp);
|
||||
if (flags & ISDOTDOT)
|
||||
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||
}
|
||||
return (VOP_CACHEDLOOKUP(dvp, vpp, cnp));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user