vfs_lookup(): Minor performance optimizations

Refactor the symlink and mountpoint traversal logic to avoid
repeatedly checking the vnode type; a symlink cannot be a mountpoint
and vice versa.  Avoid repeatedly checking cn_flags for NOCROSSMOUNT
and simplify the check which determines whether the vnode is a
mountpoint.

Suggested by:	mjg
Reviewed by:	kib
Tested by:	pho
Differential Revision:	https://reviews.freebsd.org/D35054
This commit is contained in:
Jason A. Harmening 2022-10-19 22:33:19 -05:00
parent 4390622c8d
commit f7833196bd

View File

@ -1221,47 +1221,6 @@ vfs_lookup(struct nameidata *ndp)
#endif
dp = ndp->ni_vp;
/*
* Check to see if the vnode has been mounted on;
* if so find the root of the mounted filesystem.
*/
while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
(cnp->cn_flags & NOCROSSMOUNT) == 0) {
crosslock = (dp->v_vflag & VV_CROSSLOCK) != 0;
crosslkflags = compute_cn_lkflags(mp, cnp->cn_lkflags,
cnp->cn_flags);
if (__predict_false(crosslock) &&
(crosslkflags & LK_EXCLUSIVE) != 0 &&
VOP_ISLOCKED(dp) != LK_EXCLUSIVE) {
vn_lock(dp, LK_UPGRADE | LK_RETRY);
if (VN_IS_DOOMED(dp)) {
error = ENOENT;
goto bad2;
}
}
if (vfs_busy(mp, 0))
continue;
if (__predict_true(!crosslock))
vput(dp);
if (dp != ndp->ni_dvp)
vput(ndp->ni_dvp);
else
vrele(ndp->ni_dvp);
vrefact(vp_crossmp);
ndp->ni_dvp = vp_crossmp;
error = VFS_ROOT(mp, crosslkflags, &tdp);
vfs_unbusy(mp);
if (__predict_false(crosslock))
vput(dp);
if (vn_lock(vp_crossmp, LK_SHARED | LK_NOWAIT))
panic("vp_crossmp exclusively locked or reclaimed");
if (error) {
dpunlocked = 1;
goto bad2;
}
ndp->ni_vp = dp = tdp;
}
/*
* Check for symbolic link
*/
@ -1289,7 +1248,54 @@ vfs_lookup(struct nameidata *ndp)
ni_dvp_unlocked = 1;
}
goto success;
}
} else if ((vn_irflag_read(dp) & VIRF_MOUNTPOINT) != 0) {
if ((cnp->cn_flags & NOCROSSMOUNT) != 0)
goto nextname;
} else
goto nextname;
/*
* Check to see if the vnode has been mounted on;
* if so find the root of the mounted filesystem.
*/
do {
mp = dp->v_mountedhere;
KASSERT(mp != NULL,
("%s: NULL mountpoint for VIRF_MOUNTPOINT vnode", __func__));
crosslock = (dp->v_vflag & VV_CROSSLOCK) != 0;
crosslkflags = compute_cn_lkflags(mp, cnp->cn_lkflags,
cnp->cn_flags);
if (__predict_false(crosslock) &&
(crosslkflags & LK_EXCLUSIVE) != 0 &&
VOP_ISLOCKED(dp) != LK_EXCLUSIVE) {
vn_lock(dp, LK_UPGRADE | LK_RETRY);
if (VN_IS_DOOMED(dp)) {
error = ENOENT;
goto bad2;
}
}
if (vfs_busy(mp, 0) != 0)
continue;
if (__predict_true(!crosslock))
vput(dp);
if (dp != ndp->ni_dvp)
vput(ndp->ni_dvp);
else
vrele(ndp->ni_dvp);
vrefact(vp_crossmp);
ndp->ni_dvp = vp_crossmp;
error = VFS_ROOT(mp, crosslkflags, &tdp);
vfs_unbusy(mp);
if (__predict_false(crosslock))
vput(dp);
if (vn_lock(vp_crossmp, LK_SHARED | LK_NOWAIT))
panic("vp_crossmp exclusively locked or reclaimed");
if (error != 0) {
dpunlocked = 1;
goto bad2;
}
ndp->ni_vp = dp = tdp;
} while ((vn_irflag_read(dp) & VIRF_MOUNTPOINT) != 0);
nextname:
/*