xref: /netbsd-src/sys/miscfs/nullfs/null_vfsops.c (revision 6017299f5f196c6e3948ecba1fb01ed7332db784)
1*6017299fShannken /*	$NetBSD: null_vfsops.c,v 1.101 2023/02/06 10:32:58 hannken Exp $	*/
2cf92afd6Scgd 
3cde1d475Smycroft /*
49866514dSwrstuden  * Copyright (c) 1999 National Aeronautics & Space Administration
59866514dSwrstuden  * All rights reserved.
69866514dSwrstuden  *
79866514dSwrstuden  * This software was written by William Studenmund of the
8e265f988Swiz  * Numerical Aerospace Simulation Facility, NASA Ames Research Center.
99866514dSwrstuden  *
109866514dSwrstuden  * Redistribution and use in source and binary forms, with or without
119866514dSwrstuden  * modification, are permitted provided that the following conditions
129866514dSwrstuden  * are met:
139866514dSwrstuden  * 1. Redistributions of source code must retain the above copyright
149866514dSwrstuden  *    notice, this list of conditions and the following disclaimer.
159866514dSwrstuden  * 2. Redistributions in binary form must reproduce the above copyright
169866514dSwrstuden  *    notice, this list of conditions and the following disclaimer in the
179866514dSwrstuden  *    documentation and/or other materials provided with the distribution.
1895054da1Ssoren  * 3. Neither the name of the National Aeronautics & Space Administration
199866514dSwrstuden  *    nor the names of its contributors may be used to endorse or promote
209866514dSwrstuden  *    products derived from this software without specific prior written
219866514dSwrstuden  *    permission.
229866514dSwrstuden  *
239866514dSwrstuden  * THIS SOFTWARE IS PROVIDED BY THE NATIONAL AERONAUTICS & SPACE ADMINISTRATION
249866514dSwrstuden  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
259866514dSwrstuden  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
269866514dSwrstuden  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ADMINISTRATION OR CONTRIB-
279866514dSwrstuden  * UTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
289866514dSwrstuden  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
299866514dSwrstuden  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
309866514dSwrstuden  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
319866514dSwrstuden  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
329866514dSwrstuden  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
339866514dSwrstuden  * POSSIBILITY OF SUCH DAMAGE.
349866514dSwrstuden  */
3597272194Srmind 
369866514dSwrstuden /*
37e5bc90f4Sfvdl  * Copyright (c) 1992, 1993, 1995
38cde1d475Smycroft  *	The Regents of the University of California.  All rights reserved.
39cde1d475Smycroft  *
40cde1d475Smycroft  * This code is derived from software donated to Berkeley by
41cde1d475Smycroft  * Jan-Simon Pendry.
42cde1d475Smycroft  *
43cde1d475Smycroft  * Redistribution and use in source and binary forms, with or without
44cde1d475Smycroft  * modification, are permitted provided that the following conditions
45cde1d475Smycroft  * are met:
46cde1d475Smycroft  * 1. Redistributions of source code must retain the above copyright
47cde1d475Smycroft  *    notice, this list of conditions and the following disclaimer.
48cde1d475Smycroft  * 2. Redistributions in binary form must reproduce the above copyright
49cde1d475Smycroft  *    notice, this list of conditions and the following disclaimer in the
50cde1d475Smycroft  *    documentation and/or other materials provided with the distribution.
51aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
52cde1d475Smycroft  *    may be used to endorse or promote products derived from this software
53cde1d475Smycroft  *    without specific prior written permission.
54cde1d475Smycroft  *
55cde1d475Smycroft  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56cde1d475Smycroft  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57cde1d475Smycroft  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58cde1d475Smycroft  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59cde1d475Smycroft  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60cde1d475Smycroft  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61cde1d475Smycroft  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62cde1d475Smycroft  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63cde1d475Smycroft  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64cde1d475Smycroft  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65cde1d475Smycroft  * SUCH DAMAGE.
66cde1d475Smycroft  *
67cde1d475Smycroft  *	from: Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp
68cde1d475Smycroft  *	from: @(#)lofs_vfsops.c	1.2 (Berkeley) 6/18/92
69e5bc90f4Sfvdl  *	@(#)null_vfsops.c	8.7 (Berkeley) 5/14/95
70cde1d475Smycroft  */
71cde1d475Smycroft 
72cde1d475Smycroft /*
7397272194Srmind  * Null file-system: VFS operations.
7497272194Srmind  *
7597272194Srmind  * See null_vnops.c for a description.
76cde1d475Smycroft  */
77cde1d475Smycroft 
78e4b00f43Slukem #include <sys/cdefs.h>
79*6017299fShannken __KERNEL_RCSID(0, "$NetBSD: null_vfsops.c,v 1.101 2023/02/06 10:32:58 hannken Exp $");
80e4b00f43Slukem 
81cde1d475Smycroft #include <sys/param.h>
82cde1d475Smycroft #include <sys/systm.h>
8313f8d2ceSatatat #include <sys/sysctl.h>
84cde1d475Smycroft #include <sys/vnode.h>
85cde1d475Smycroft #include <sys/mount.h>
86cde1d475Smycroft #include <sys/namei.h>
87a1221b6dSrumble #include <sys/module.h>
88579ece84Senami 
89cde1d475Smycroft #include <miscfs/nullfs/null.h>
909866514dSwrstuden #include <miscfs/genfs/layer_extern.h>
91cde1d475Smycroft 
9206c33973Sjld MODULE(MODULE_CLASS_VFS, null, "layerfs");
93a1221b6dSrumble 
948d1f8992Spooka VFS_PROTOS(nullfs);
959866514dSwrstuden 
96cde1d475Smycroft int
nullfs_mount(struct mount * mp,const char * path,void * data,size_t * data_len)97454af1c0Sdsl nullfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
98cde1d475Smycroft {
99cde1d475Smycroft 	struct vnode *lowerrootvp, *vp;
10097272194Srmind 	struct null_args *args = data;
1019866514dSwrstuden 	struct null_mount *nmp;
1029866514dSwrstuden 	struct layer_mount *lmp;
1038f6ed30dSdholland 	struct pathbuf *pb;
10497272194Srmind 	struct nameidata nd;
10597272194Srmind 	int error;
106cde1d475Smycroft 
10723f76b6dSmaxv 	if (args == NULL)
10823f76b6dSmaxv 		return EINVAL;
10997272194Srmind 	if (*data_len < sizeof(*args))
1102721ab6cSdsl 		return EINVAL;
1112721ab6cSdsl 
1126868d0a7Schristos 	if (mp->mnt_flag & MNT_GETARGS) {
1136868d0a7Schristos 		lmp = MOUNTTOLAYERMOUNT(mp);
1146868d0a7Schristos 		if (lmp == NULL)
1156868d0a7Schristos 			return EIO;
1162721ab6cSdsl 		args->la.target = NULL;
11797272194Srmind 		*data_len = sizeof(*args);
1182721ab6cSdsl 		return 0;
1196868d0a7Schristos 	}
120cde1d475Smycroft 
12197272194Srmind 	/* Update is not supported. */
1222a3e5eebSjmmv 	if (mp->mnt_flag & MNT_UPDATE)
1232a3e5eebSjmmv 		return EOPNOTSUPP;
1249866514dSwrstuden 
12597272194Srmind 	/* Find the lower vnode and lock it. */
1268f6ed30dSdholland 	error = pathbuf_copyin(args->la.target, &pb);
1278f6ed30dSdholland 	if (error) {
1288f6ed30dSdholland 		return error;
1298f6ed30dSdholland 	}
1308f6ed30dSdholland 	NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF, pb);
13197272194Srmind 	if ((error = namei(&nd)) != 0) {
1328f6ed30dSdholland 		pathbuf_destroy(pb);
13397272194Srmind 		return error;
13497272194Srmind 	}
1358d1f8992Spooka 	lowerrootvp = nd.ni_vp;
1368f6ed30dSdholland 	pathbuf_destroy(pb);
137cde1d475Smycroft 
13897272194Srmind 	/* Create the mount point. */
139f1d428afSrmind 	nmp = kmem_zalloc(sizeof(struct null_mount), KM_SLEEP);
140178d83d5Ssoren 	mp->mnt_data = nmp;
141*6017299fShannken 	mp->mnt_iflag |= lowerrootvp->v_mount->mnt_iflag & IMNT_MPSAFE;
142c90f9c8cSad 	mp->mnt_iflag |= lowerrootvp->v_mount->mnt_iflag & IMNT_SHRLOOKUP;
143cde1d475Smycroft 
144cde1d475Smycroft 	/*
1459866514dSwrstuden 	 * Make sure that the mount point is sufficiently initialized
1469866514dSwrstuden 	 * that the node create call will work.
147cde1d475Smycroft 	 */
1486c734cd2Sassar 	vfs_getnewfsid(mp);
149cfe3f2c3Shannken 	error = vfs_set_lowermount(mp, lowerrootvp->v_mount);
150cfe3f2c3Shannken 	if (error) {
151cfe3f2c3Shannken 		vput(lowerrootvp);
152cfe3f2c3Shannken 		kmem_free(nmp, sizeof(struct null_mount));
153cfe3f2c3Shannken 		return error;
154cfe3f2c3Shannken 	}
1559866514dSwrstuden 
1569866514dSwrstuden 	nmp->nullm_size = sizeof(struct null_node);
1579866514dSwrstuden 	nmp->nullm_tag = VT_NULL;
1589866514dSwrstuden 	nmp->nullm_bypass = layer_bypass;
1599866514dSwrstuden 	nmp->nullm_vnodeop_p = null_vnodeop_p;
160cde1d475Smycroft 
16197272194Srmind 	/* Setup a null node for root vnode. */
16286536158Shannken 	VOP_UNLOCK(lowerrootvp);
1639866514dSwrstuden 	error = layer_node_create(mp, lowerrootvp, &vp);
164cde1d475Smycroft 	if (error) {
16586536158Shannken 		vrele(lowerrootvp);
166f1d428afSrmind 		kmem_free(nmp, sizeof(struct null_mount));
16797272194Srmind 		return error;
168cde1d475Smycroft 	}
169872d72e7Swrstuden 	/*
17097272194Srmind 	 * Keep a held reference to the root vnode.  It will be released on
17197272194Srmind 	 * umount.  Note: nullfs is MP-safe.
172cde1d475Smycroft 	 */
17386536158Shannken 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1744a780c9aSad 	vp->v_vflag |= VV_ROOT;
1759866514dSwrstuden 	nmp->nullm_rootvp = vp;
1761423e65bShannken 	VOP_UNLOCK(vp);
1774a780c9aSad 
1782721ab6cSdsl 	error = set_statvfs_info(path, UIO_USERSPACE, args->la.target,
17997272194Srmind 	    UIO_USERSPACE, mp->mnt_op->vfs_name, mp, curlwp);
180dd67c605Shannken 	if (error)
18180ecd573Schristos 		return error;
182228d72edShannken 
183228d72edShannken 	if (mp->mnt_lower->mnt_flag & MNT_LOCAL)
184228d72edShannken 		mp->mnt_flag |= MNT_LOCAL;
185dd67c605Shannken 	return 0;
186cde1d475Smycroft }
187cde1d475Smycroft 
188cde1d475Smycroft int
nullfs_unmount(struct mount * mp,int mntflags)18961e8303eSpooka nullfs_unmount(struct mount *mp, int mntflags)
190cde1d475Smycroft {
191888e968eSenami 	struct null_mount *nmp = MOUNTTONULLMOUNT(mp);
192888e968eSenami 	struct vnode *null_rootvp = nmp->nullm_rootvp;
19397272194Srmind 	int error, flags = 0;
194cde1d475Smycroft 
195e5bc90f4Sfvdl 	if (mntflags & MNT_FORCE)
196cde1d475Smycroft 		flags |= FORCECLOSE;
197cde1d475Smycroft 
19823bf8800Sad 	if (vrefcnt(null_rootvp) > 1 && (mntflags & MNT_FORCE) == 0)
19997272194Srmind 		return EBUSY;
200cde1d475Smycroft 
20197272194Srmind 	if ((error = vflush(mp, null_rootvp, flags)) != 0)
20297272194Srmind 		return error;
20397272194Srmind 
20497272194Srmind 	/* Eliminate all activity and release the vnode. */
2059866514dSwrstuden 	vgone(null_rootvp);
206579ece84Senami 
20797272194Srmind 	/* Finally, destroy the mount point structures. */
208f1d428afSrmind 	kmem_free(mp->mnt_data, sizeof(struct null_mount));
209579ece84Senami 	mp->mnt_data = NULL;
21097272194Srmind 	return 0;
211cde1d475Smycroft }
212cde1d475Smycroft 
213d9466585Sjdolecek extern const struct vnodeopv_desc null_vnodeop_opv_desc;
214b5bf2ed6Sthorpej 
215d9466585Sjdolecek const struct vnodeopv_desc * const nullfs_vnodeopv_descs[] = {
216e5bc90f4Sfvdl 	&null_vnodeop_opv_desc,
217b5bf2ed6Sthorpej 	NULL,
218b5bf2ed6Sthorpej };
219b5bf2ed6Sthorpej 
220c9efd056Sthorpej struct vfsops nullfs_vfsops = {
2216d285189Shannken 	.vfs_name = MOUNT_NULL,
2226d285189Shannken 	.vfs_min_mount_data = sizeof (struct null_args),
2236d285189Shannken 	.vfs_mount = nullfs_mount,
2246d285189Shannken 	.vfs_start = layerfs_start,
2256d285189Shannken 	.vfs_unmount = nullfs_unmount,
2266d285189Shannken 	.vfs_root = layerfs_root,
2276d285189Shannken 	.vfs_quotactl = layerfs_quotactl,
2286d285189Shannken 	.vfs_statvfs = layerfs_statvfs,
2296d285189Shannken 	.vfs_sync = layerfs_sync,
23055de4c18Shannken 	.vfs_loadvnode = layerfs_loadvnode,
2316d285189Shannken 	.vfs_vget = layerfs_vget,
2326d285189Shannken 	.vfs_fhtovp = layerfs_fhtovp,
2336d285189Shannken 	.vfs_vptofh = layerfs_vptofh,
2346d285189Shannken 	.vfs_init = layerfs_init,
2356d285189Shannken 	.vfs_done = layerfs_done,
2366d285189Shannken 	.vfs_snapshot = layerfs_snapshot,
2376d285189Shannken 	.vfs_extattrctl = vfs_stdextattrctl,
238326db3aaShannken 	.vfs_suspendctl = layerfs_suspendctl,
2396d285189Shannken 	.vfs_renamelock_enter = layerfs_renamelock_enter,
2406d285189Shannken 	.vfs_renamelock_exit = layerfs_renamelock_exit,
2416d285189Shannken 	.vfs_fsync = (void *)eopnotsupp,
2426d285189Shannken 	.vfs_opv_descs = nullfs_vnodeopv_descs
243cde1d475Smycroft };
244a1221b6dSrumble 
2459120d451Spgoyette SYSCTL_SETUP(nullfs_sysctl_setup, "nullfs sysctl")
246a1221b6dSrumble {
247a1221b6dSrumble 
2489120d451Spgoyette 	sysctl_createv(clog, 0, NULL, NULL,
249a8ced4f0Sad 	    CTLFLAG_PERMANENT,
250a8ced4f0Sad 	    CTLTYPE_NODE, "null",
251a8ced4f0Sad 	    SYSCTL_DESCR("Loopback file system"),
252a8ced4f0Sad 	    NULL, 0, NULL, 0,
253a8ced4f0Sad 	    CTL_VFS, 9, CTL_EOL);
254a8ced4f0Sad 	/*
255a8ced4f0Sad 	 * XXX the "9" above could be dynamic, thereby eliminating
256a8ced4f0Sad 	 * one more instance of the "number to vfs" mapping problem,
257a8ced4f0Sad 	 * but "9" is the order as taken from sys/mount.h
258a8ced4f0Sad 	 */
2599120d451Spgoyette }
2609120d451Spgoyette 
2619120d451Spgoyette static int
null_modcmd(modcmd_t cmd,void * arg)2629120d451Spgoyette null_modcmd(modcmd_t cmd, void *arg)
2639120d451Spgoyette {
2649120d451Spgoyette 	int error;
2659120d451Spgoyette 
2669120d451Spgoyette 	switch (cmd) {
2679120d451Spgoyette 	case MODULE_CMD_INIT:
2689120d451Spgoyette 		error = vfs_attach(&nullfs_vfsops);
2699120d451Spgoyette 		if (error != 0)
2709120d451Spgoyette 			break;
271a8ced4f0Sad 		break;
272a1221b6dSrumble 	case MODULE_CMD_FINI:
273a8ced4f0Sad 		error = vfs_detach(&nullfs_vfsops);
274a8ced4f0Sad 		if (error != 0)
275a8ced4f0Sad 			break;
276a8ced4f0Sad 		break;
277a1221b6dSrumble 	default:
278a8ced4f0Sad 		error = ENOTTY;
279a8ced4f0Sad 		break;
280a1221b6dSrumble 	}
281a8ced4f0Sad 	return error;
282a1221b6dSrumble }
283