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