Un null_vptocnp(), cache vp->v_mount and use it for null_nodeget() call.

The vp vnode is unlocked during the execution of the VOP method and
can be reclaimed, zeroing vp->v_data.  Caching allows to use the
correct mount point.

Reported and tested by:	pho
PR: 235549
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2019-02-08 08:20:18 +00:00
parent 25728e8411
commit b9662886ef
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=343899

View File

@ -870,11 +870,14 @@ null_vptocnp(struct vop_vptocnp_args *ap)
struct vnode **dvp = ap->a_vpp; struct vnode **dvp = ap->a_vpp;
struct vnode *lvp, *ldvp; struct vnode *lvp, *ldvp;
struct ucred *cred = ap->a_cred; struct ucred *cred = ap->a_cred;
struct mount *mp;
int error, locked; int error, locked;
locked = VOP_ISLOCKED(vp); locked = VOP_ISLOCKED(vp);
lvp = NULLVPTOLOWERVP(vp); lvp = NULLVPTOLOWERVP(vp);
vhold(lvp); vhold(lvp);
mp = vp->v_mount;
vfs_ref(mp);
VOP_UNLOCK(vp, 0); /* vp is held by vn_vptocnp_locked that called us */ VOP_UNLOCK(vp, 0); /* vp is held by vn_vptocnp_locked that called us */
ldvp = lvp; ldvp = lvp;
vref(lvp); vref(lvp);
@ -882,6 +885,7 @@ null_vptocnp(struct vop_vptocnp_args *ap)
vdrop(lvp); vdrop(lvp);
if (error != 0) { if (error != 0) {
vn_lock(vp, locked | LK_RETRY); vn_lock(vp, locked | LK_RETRY);
vfs_rel(mp);
return (ENOENT); return (ENOENT);
} }
@ -893,9 +897,10 @@ null_vptocnp(struct vop_vptocnp_args *ap)
if (error != 0) { if (error != 0) {
vrele(ldvp); vrele(ldvp);
vn_lock(vp, locked | LK_RETRY); vn_lock(vp, locked | LK_RETRY);
vfs_rel(mp);
return (ENOENT); return (ENOENT);
} }
error = null_nodeget(vp->v_mount, ldvp, dvp); error = null_nodeget(mp, ldvp, dvp);
if (error == 0) { if (error == 0) {
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
NULLVPTOLOWERVP(*dvp); NULLVPTOLOWERVP(*dvp);
@ -903,6 +908,7 @@ null_vptocnp(struct vop_vptocnp_args *ap)
VOP_UNLOCK(*dvp, 0); /* keep reference on *dvp */ VOP_UNLOCK(*dvp, 0); /* keep reference on *dvp */
} }
vn_lock(vp, locked | LK_RETRY); vn_lock(vp, locked | LK_RETRY);
vfs_rel(mp);
return (error); return (error);
} }