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