diff options
Diffstat (limited to 'sys/fs/nullfs')
| -rw-r--r-- | sys/fs/nullfs/null.h | 13 | ||||
| -rw-r--r-- | sys/fs/nullfs/null_subr.c | 4 | ||||
| -rw-r--r-- | sys/fs/nullfs/null_vfsops.c | 20 | ||||
| -rw-r--r-- | sys/fs/nullfs/null_vnops.c | 10 | 
4 files changed, 40 insertions, 7 deletions
| diff --git a/sys/fs/nullfs/null.h b/sys/fs/nullfs/null.h index 3ae0cd02b2b6..eebf6da571b8 100644 --- a/sys/fs/nullfs/null.h +++ b/sys/fs/nullfs/null.h @@ -37,7 +37,8 @@  #ifndef	FS_NULL_H  #define	FS_NULL_H -#define	NULLM_CACHE	0x0001 +#define	NULLM_CACHE		0x0001 +#define	NULLM_NOUNPBYPASS	0x0002  struct null_mount {  	struct mount	*nullm_vfs; @@ -80,6 +81,16 @@ struct vnode *null_checkvp(struct vnode *vp, char *fil, int lno);  #endif  extern struct vop_vector null_vnodeops; +extern struct vop_vector null_vnodeops_no_unp_bypass; + +static inline bool +null_is_nullfs_vnode(struct vnode *vp) +{ +	const struct vop_vector *op; + +	op = vp->v_op; +	return (op == &null_vnodeops || op == &null_vnodeops_no_unp_bypass); +}  #ifdef MALLOC_DECLARE  MALLOC_DECLARE(M_NULLFSNODE); diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c index 546f0aea3766..b0e3d15b4789 100644 --- a/sys/fs/nullfs/null_subr.c +++ b/sys/fs/nullfs/null_subr.c @@ -212,7 +212,9 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)  	 */  	xp = malloc(sizeof(struct null_node), M_NULLFSNODE, M_WAITOK); -	error = getnewvnode("nullfs", mp, &null_vnodeops, &vp); +	error = getnewvnode("nullfs", mp, (MOUNTTONULLMOUNT(mp)->nullm_flags & +	    NULLM_NOUNPBYPASS) != 0 ? &null_vnodeops_no_unp_bypass : +	    &null_vnodeops, &vp);  	if (error) {  		vput(lowervp);  		free(xp, M_NULLFSNODE); diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index 8d980932623d..8b9e04775449 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -89,6 +89,10 @@ nullfs_mount(struct mount *mp)  	char *target;  	int error, len;  	bool isvnunlocked; +	static const char cache_opt_name[] = "cache"; +	static const char nocache_opt_name[] = "nocache"; +	static const char unixbypass_opt_name[] = "unixbypass"; +	static const char nounixbypass_opt_name[] = "nounixbypass";  	NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp); @@ -120,7 +124,7 @@ nullfs_mount(struct mount *mp)  	/*  	 * Unlock lower node to avoid possible deadlock.  	 */ -	if (mp->mnt_vnodecovered->v_op == &null_vnodeops && +	if (null_is_nullfs_vnode(mp->mnt_vnodecovered) &&  	    VOP_ISLOCKED(mp->mnt_vnodecovered) == LK_EXCLUSIVE) {  		VOP_UNLOCK(mp->mnt_vnodecovered);  		isvnunlocked = true; @@ -154,7 +158,7 @@ nullfs_mount(struct mount *mp)  	/*  	 * Check multi null mount to avoid `lock against myself' panic.  	 */ -	if (mp->mnt_vnodecovered->v_op == &null_vnodeops) { +	if (null_is_nullfs_vnode(mp->mnt_vnodecovered)) {  		nn = VTONULL(mp->mnt_vnodecovered);  		if (nn == NULL || lowerrootvp == nn->null_lowervp) {  			NULLFSDEBUG("nullfs_mount: multi null mount?\n"); @@ -209,9 +213,10 @@ nullfs_mount(struct mount *mp)  		MNT_IUNLOCK(mp);  	} -	if (vfs_getopt(mp->mnt_optnew, "cache", NULL, NULL) == 0) { +	if (vfs_getopt(mp->mnt_optnew, cache_opt_name, NULL, NULL) == 0) {  		xmp->nullm_flags |= NULLM_CACHE; -	} else if (vfs_getopt(mp->mnt_optnew, "nocache", NULL, NULL) == 0) { +	} else if (vfs_getopt(mp->mnt_optnew, nocache_opt_name, NULL, +	    NULL) == 0) {  		;  	} else if (null_cache_vnodes &&  	    (xmp->nullm_vfs->mnt_kern_flag & MNTK_NULL_NOCACHE) == 0) { @@ -223,6 +228,13 @@ nullfs_mount(struct mount *mp)  		    &xmp->notify_node);  	} +	if (vfs_getopt(mp->mnt_optnew, unixbypass_opt_name, NULL, NULL) == 0) { +		; +	} else if (vfs_getopt(mp->mnt_optnew, nounixbypass_opt_name, NULL, +	    NULL) == 0) { +		xmp->nullm_flags |= NULLM_NOUNPBYPASS; +	} +  	if (lowerrootvp == mp->mnt_vnodecovered) {  		vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE);  		lowerrootvp->v_vflag |= VV_CROSSLOCK; diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c index 41915da7f13c..2e34b77a5a7e 100644 --- a/sys/fs/nullfs/null_vnops.c +++ b/sys/fs/nullfs/null_vnops.c @@ -258,7 +258,7 @@ null_bypass(struct vop_generic_args *ap)  		 * that aren't.  (We must always map first vp or vclean fails.)  		 */  		if (i != 0 && (*this_vp_p == NULLVP || -		    (*this_vp_p)->v_op != &null_vnodeops)) { +		    !null_is_nullfs_vnode(*this_vp_p))) {  			old_vps[i] = NULLVP;  		} else {  			old_vps[i] = *this_vp_p; @@ -1192,3 +1192,11 @@ struct vop_vector null_vnodeops = {  	.vop_copy_file_range =	VOP_PANIC,  };  VFS_VOP_VECTOR_REGISTER(null_vnodeops); + +struct vop_vector null_vnodeops_no_unp_bypass = { +	.vop_default =		&null_vnodeops, +	.vop_unp_bind =		vop_stdunp_bind, +	.vop_unp_connect =	vop_stdunp_connect, +	.vop_unp_detach =	vop_stdunp_detach, +}; +VFS_VOP_VECTOR_REGISTER(null_vnodeops_no_unp_bypass); | 
