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:
parent
25728e8411
commit
b9662886ef
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=343899
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user