diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2021-01-24 13:22:48 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2021-02-25 20:48:37 +0000 |
commit | b4cc32336d31c8d81feaae2aab4d1d2fd9f306a5 (patch) | |
tree | 6dc8b4aa3ca02e158627a0b1a000100676af0eb2 | |
parent | 984c11f5aaa02883d1afbbca31b419194005ac4c (diff) | |
download | src-b4cc32336d31c8d81feaae2aab4d1d2fd9f306a5.tar.gz src-b4cc32336d31c8d81feaae2aab4d1d2fd9f306a5.zip |
nullfs: provide special bypass for VOP_VPUT_PAIR
Approved by: re (delphij, gjb)
(cherry picked from commit e4aaf35ab54958f74409790fa2b7df8c2d230cee)
-rw-r--r-- | sys/fs/nullfs/null_vnops.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 1de0cdfca9ac..45065e0be7b5 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -968,6 +968,54 @@ null_read_pgcache(struct vop_read_pgcache_args *ap) } /* + * Avoid standard bypass, since lower dvp and vp could be no longer + * valid after vput(). + */ +static int +null_vput_pair(struct vop_vput_pair_args *ap) +{ + struct mount *mp; + struct vnode *dvp, *ldvp, *lvp, *vp, *vp1, **vpp; + int error, res; + + dvp = ap->a_dvp; + ldvp = NULLVPTOLOWERVP(dvp); + vref(ldvp); + + vpp = ap->a_vpp; + vp = NULL; + lvp = NULL; + if (vpp != NULL) { + vp = *vpp; + if (vp != NULL) { + vhold(vp); + mp = vp->v_mount; + lvp = NULLVPTOLOWERVP(vp); + if (ap->a_unlock_vp) + vref(lvp); + } + } + + res = VOP_VPUT_PAIR(ldvp, &lvp, ap->a_unlock_vp); + + /* lvp might have been unlocked and vp reclaimed */ + if (vp != NULL) { + if (!ap->a_unlock_vp && vp->v_vnlock != lvp->v_vnlock) { + error = null_nodeget(mp, lvp, &vp1); + if (error == 0) { + vput(vp); + *vpp = vp1; + } + } + if (ap->a_unlock_vp) + vrele(vp); + vdrop(vp); + } + vrele(dvp); + return (res); +} + +/* * Global vfs data structures */ struct vop_vector null_vnodeops = { @@ -997,5 +1045,6 @@ struct vop_vector null_vnodeops = { .vop_vptocnp = null_vptocnp, .vop_vptofh = null_vptofh, .vop_add_writecount = null_add_writecount, + .vop_vput_pair = null_vput_pair, }; VFS_VOP_VECTOR_REGISTER(null_vnodeops); |