nullfs: provide custom bypass for VOP_READ_PGCACHE().
Normal bypass expects locked vnode, which is not true for VOP_READ_PGCACHE(). Ensure liveness of the lower vnode by taking the upper vnode interlock, which is also taked by null_reclaim() when setting v_data to NULL. Reported and tested by: pho Reviewed by: markj, mjg Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D27327
This commit is contained in:
parent
1cede83674
commit
3d3de5ce17
@ -947,6 +947,28 @@ null_vptocnp(struct vop_vptocnp_args *ap)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
null_read_pgcache(struct vop_read_pgcache_args *ap)
|
||||||
|
{
|
||||||
|
struct vnode *lvp, *vp;
|
||||||
|
struct null_node *xp;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
vp = ap->a_vp;
|
||||||
|
VI_LOCK(vp);
|
||||||
|
xp = VTONULL(vp);
|
||||||
|
if (xp == NULL) {
|
||||||
|
VI_UNLOCK(vp);
|
||||||
|
return (EJUSTRETURN);
|
||||||
|
}
|
||||||
|
lvp = xp->null_lowervp;
|
||||||
|
vref(lvp);
|
||||||
|
VI_UNLOCK(vp);
|
||||||
|
error = VOP_READ_PGCACHE(lvp, ap->a_uio, ap->a_ioflag, ap->a_cred);
|
||||||
|
vrele(lvp);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global vfs data structures
|
* Global vfs data structures
|
||||||
*/
|
*/
|
||||||
@ -966,6 +988,7 @@ struct vop_vector null_vnodeops = {
|
|||||||
.vop_lookup = null_lookup,
|
.vop_lookup = null_lookup,
|
||||||
.vop_open = null_open,
|
.vop_open = null_open,
|
||||||
.vop_print = null_print,
|
.vop_print = null_print,
|
||||||
|
.vop_read_pgcache = null_read_pgcache,
|
||||||
.vop_reclaim = null_reclaim,
|
.vop_reclaim = null_reclaim,
|
||||||
.vop_remove = null_remove,
|
.vop_remove = null_remove,
|
||||||
.vop_rename = null_rename,
|
.vop_rename = null_rename,
|
||||||
|
Loading…
Reference in New Issue
Block a user