1*23bf8800Sad /* $NetBSD: fdesc_vfsops.c,v 1.96 2020/04/13 19:23:18 ad Exp $ */
2cf92afd6Scgd
3e6035453Scgd /*
4e5bc90f4Sfvdl * Copyright (c) 1992, 1993, 1995
5cde1d475Smycroft * The Regents of the University of California. All rights reserved.
6e6035453Scgd *
74942f8a8Scgd * This code is derived from software donated to Berkeley by
8e6035453Scgd * Jan-Simon Pendry.
9e6035453Scgd *
10320661fcScgd * Redistribution and use in source and binary forms, with or without
11320661fcScgd * modification, are permitted provided that the following conditions
12320661fcScgd * are met:
13320661fcScgd * 1. Redistributions of source code must retain the above copyright
14320661fcScgd * notice, this list of conditions and the following disclaimer.
15320661fcScgd * 2. Redistributions in binary form must reproduce the above copyright
16320661fcScgd * notice, this list of conditions and the following disclaimer in the
17320661fcScgd * documentation and/or other materials provided with the distribution.
18aad01611Sagc * 3. Neither the name of the University nor the names of its contributors
19320661fcScgd * may be used to endorse or promote products derived from this software
20320661fcScgd * without specific prior written permission.
21e6035453Scgd *
22320661fcScgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23320661fcScgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24320661fcScgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25320661fcScgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26320661fcScgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27320661fcScgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28320661fcScgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29320661fcScgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30320661fcScgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31320661fcScgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32320661fcScgd * SUCH DAMAGE.
33e6035453Scgd *
34e5bc90f4Sfvdl * @(#)fdesc_vfsops.c 8.10 (Berkeley) 5/14/95
352981ef65Smycroft *
362981ef65Smycroft * #Id: fdesc_vfsops.c,v 1.9 1993/04/06 15:28:33 jsp Exp #
37e6035453Scgd */
38e6035453Scgd
39e6035453Scgd /*
40e6035453Scgd * /dev/fd Filesystem
41e6035453Scgd */
42e6035453Scgd
43e4b00f43Slukem #include <sys/cdefs.h>
44*23bf8800Sad __KERNEL_RCSID(0, "$NetBSD: fdesc_vfsops.c,v 1.96 2020/04/13 19:23:18 ad Exp $");
45e4b00f43Slukem
4667afbd62Smrg #if defined(_KERNEL_OPT)
47d275e56dSjonathan #include "opt_compat_netbsd.h"
48d275e56dSjonathan #endif
49d275e56dSjonathan
504942f8a8Scgd #include <sys/param.h>
514942f8a8Scgd #include <sys/systm.h>
5213f8d2ceSatatat #include <sys/sysctl.h>
534942f8a8Scgd #include <sys/time.h>
544942f8a8Scgd #include <sys/proc.h>
554942f8a8Scgd #include <sys/resourcevar.h>
564942f8a8Scgd #include <sys/filedesc.h>
574942f8a8Scgd #include <sys/vnode.h>
584942f8a8Scgd #include <sys/mount.h>
594bdb8083Schristos #include <sys/dirent.h>
604942f8a8Scgd #include <sys/namei.h>
61fc9422c9Selad #include <sys/kauth.h>
62a1221b6dSrumble #include <sys/module.h>
63fc9422c9Selad
64717e1785Sdholland #include <miscfs/genfs/genfs.h>
654942f8a8Scgd #include <miscfs/fdesc/fdesc.h>
66e6035453Scgd
67a1221b6dSrumble MODULE(MODULE_CLASS_VFS, fdesc, NULL);
68a1221b6dSrumble
698d1f8992Spooka VFS_PROTOS(fdesc);
70631ccba6Schristos
71e6035453Scgd /*
72e6035453Scgd * Mount the per-process file descriptors (/dev/fd)
73e6035453Scgd */
74cde1d475Smycroft int
fdesc_mount(struct mount * mp,const char * path,void * data,size_t * data_len)7561e8303eSpooka fdesc_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
76e6035453Scgd {
7761e8303eSpooka struct lwp *l = curlwp;
783e04c969Shannken int error = 0, ix;
79e6035453Scgd struct vnode *rvp;
80e6035453Scgd
812721ab6cSdsl if (mp->mnt_flag & MNT_GETARGS) {
822721ab6cSdsl *data_len = 0;
836868d0a7Schristos return 0;
842721ab6cSdsl }
85e6035453Scgd /*
86e6035453Scgd * Update is a no-op
87e6035453Scgd */
88e6035453Scgd if (mp->mnt_flag & MNT_UPDATE)
89e6035453Scgd return (EOPNOTSUPP);
90e6035453Scgd
913e04c969Shannken ix = FD_ROOT;
923e04c969Shannken error = vcache_get(mp, &ix, sizeof(ix), &rvp);
93e6035453Scgd if (error)
943e04c969Shannken return error;
95e6035453Scgd
967004654cSchristos mp->mnt_stat.f_namemax = FDESC_MAXNAMLEN;
97cab4d25cSmycroft mp->mnt_flag |= MNT_LOCAL;
98288dd7d6Spooka mp->mnt_data = rvp;
996c734cd2Sassar vfs_getnewfsid(mp);
100e6035453Scgd
1016bd1d6d4Schristos error = set_statvfs_info(path, UIO_USERSPACE, "fdesc", UIO_SYSSPACE,
102e24b0872Spooka mp->mnt_op->vfs_name, mp, l);
10380ecd573Schristos return error;
104e6035453Scgd }
105e6035453Scgd
106cde1d475Smycroft int
fdesc_start(struct mount * mp,int flags)10761e8303eSpooka fdesc_start(struct mount *mp, int flags)
108e6035453Scgd {
109e6035453Scgd return (0);
110e6035453Scgd }
111e6035453Scgd
112cde1d475Smycroft int
fdesc_unmount(struct mount * mp,int mntflags)11361e8303eSpooka fdesc_unmount(struct mount *mp, int mntflags)
114e6035453Scgd {
115e6035453Scgd int error;
116e6035453Scgd int flags = 0;
117288dd7d6Spooka struct vnode *rtvp = mp->mnt_data;
118e6035453Scgd
119e5bc90f4Sfvdl if (mntflags & MNT_FORCE)
120e6035453Scgd flags |= FORCECLOSE;
121e6035453Scgd
122*23bf8800Sad if (vrefcnt(rtvp) > 1 && (mntflags & MNT_FORCE) == 0)
123e6035453Scgd return (EBUSY);
124c107ef9eSchristos if ((error = vflush(mp, rtvp, flags)) != 0)
125e6035453Scgd return (error);
126e6035453Scgd
127e6035453Scgd /*
1284a780c9aSad * Blow it away for future re-use
129e6035453Scgd */
130c107ef9eSchristos vgone(rtvp);
1312fd51303Ssimonb mp->mnt_data = NULL;
132cde1d475Smycroft
133cde1d475Smycroft return (0);
134e6035453Scgd }
135e6035453Scgd
136cde1d475Smycroft int
fdesc_root(struct mount * mp,int lktype,struct vnode ** vpp)137c2e9cb94Sad fdesc_root(struct mount *mp, int lktype, struct vnode **vpp)
138e6035453Scgd {
139e6035453Scgd struct vnode *vp;
140e6035453Scgd
141e6035453Scgd /*
142e6035453Scgd * Return locked reference to root.
143e6035453Scgd */
144288dd7d6Spooka vp = mp->mnt_data;
145c3183f32Spooka vref(vp);
146c2e9cb94Sad vn_lock(vp, lktype | LK_RETRY);
147e6035453Scgd *vpp = vp;
148e6035453Scgd return (0);
149e6035453Scgd }
150e6035453Scgd
151631ccba6Schristos /*ARGSUSED*/
152cde1d475Smycroft int
fdesc_sync(struct mount * mp,int waitfor,kauth_cred_t uc)153168cd830Schristos fdesc_sync(struct mount *mp, int waitfor,
15461e8303eSpooka kauth_cred_t uc)
155e6035453Scgd {
156cde1d475Smycroft
157e6035453Scgd return (0);
158e6035453Scgd }
159e6035453Scgd
160cde1d475Smycroft /*
161cde1d475Smycroft * Fdesc flat namespace lookup.
162cde1d475Smycroft * Currently unsupported.
163cde1d475Smycroft */
164cde1d475Smycroft int
fdesc_vget(struct mount * mp,ino_t ino,int lktype,struct vnode ** vpp)165c2e9cb94Sad fdesc_vget(struct mount *mp, ino_t ino, int lktype,
166168cd830Schristos struct vnode **vpp)
167e6035453Scgd {
168cde1d475Smycroft
169e6035453Scgd return (EOPNOTSUPP);
170e6035453Scgd }
171e6035453Scgd
1723e04c969Shannken int
fdesc_loadvnode(struct mount * mp,struct vnode * vp,const void * key,size_t key_len,const void ** new_key)1733e04c969Shannken fdesc_loadvnode(struct mount *mp, struct vnode *vp,
1743e04c969Shannken const void *key, size_t key_len, const void **new_key)
1753e04c969Shannken {
1763e04c969Shannken int ix;
1773e04c969Shannken struct fdescnode *fd;
1783e04c969Shannken
1793e04c969Shannken KASSERT(key_len == sizeof(ix));
1803e04c969Shannken memcpy(&ix, key, key_len);
1813e04c969Shannken
1823e04c969Shannken fd = kmem_alloc(sizeof(struct fdescnode), KM_SLEEP);
1833e04c969Shannken fd->fd_fd = -1;
1843e04c969Shannken fd->fd_link = NULL;
1853e04c969Shannken fd->fd_ix = ix;
1863e04c969Shannken fd->fd_vnode = vp;
1873e04c969Shannken vp->v_tag = VT_FDESC;
1883e04c969Shannken vp->v_op = fdesc_vnodeop_p;
1893e04c969Shannken vp->v_data = fd;
1903e04c969Shannken switch (ix) {
1913e04c969Shannken case FD_ROOT:
1923e04c969Shannken fd->fd_type = Froot;
1933e04c969Shannken vp->v_type = VDIR;
1943e04c969Shannken vp->v_vflag |= VV_ROOT;
1953e04c969Shannken break;
1963e04c969Shannken case FD_DEVFD:
1973e04c969Shannken fd->fd_type = Fdevfd;
1983e04c969Shannken vp->v_type = VDIR;
1993e04c969Shannken break;
2003e04c969Shannken case FD_CTTY:
2013e04c969Shannken fd->fd_type = Fctty;
2025a211192Schristos vp->v_type = VCHR;
2033e04c969Shannken break;
2043e04c969Shannken case FD_STDIN:
2053e04c969Shannken fd->fd_type = Flink;
2063e04c969Shannken fd->fd_link = "fd/0";
2073e04c969Shannken vp->v_type = VLNK;
2083e04c969Shannken break;
2093e04c969Shannken case FD_STDOUT:
2103e04c969Shannken fd->fd_type = Flink;
2113e04c969Shannken fd->fd_link = "fd/1";
2123e04c969Shannken vp->v_type = VLNK;
2133e04c969Shannken break;
2143e04c969Shannken case FD_STDERR:
2153e04c969Shannken fd->fd_type = Flink;
2163e04c969Shannken fd->fd_link = "fd/2";
2173e04c969Shannken vp->v_type = VLNK;
2183e04c969Shannken break;
2193e04c969Shannken default:
2203e04c969Shannken KASSERT(ix >= FD_DESC);
2213e04c969Shannken fd->fd_type = Fdesc;
2223e04c969Shannken fd->fd_fd = ix - FD_DESC;
2233e04c969Shannken vp->v_type = VNON;
2243e04c969Shannken break;
2253e04c969Shannken }
2263e04c969Shannken uvm_vnp_setsize(vp, 0);
2273e04c969Shannken *new_key = &fd->fd_ix;
2283e04c969Shannken
2293e04c969Shannken return 0;
2303e04c969Shannken }
2313e04c969Shannken
232d9466585Sjdolecek extern const struct vnodeopv_desc fdesc_vnodeop_opv_desc;
23362cb255dSthorpej
234d9466585Sjdolecek const struct vnodeopv_desc * const fdesc_vnodeopv_descs[] = {
23562cb255dSthorpej &fdesc_vnodeop_opv_desc,
23662cb255dSthorpej NULL,
23762cb255dSthorpej };
23862cb255dSthorpej
239e6035453Scgd struct vfsops fdesc_vfsops = {
2406d285189Shannken .vfs_name = MOUNT_FDESC,
2416d285189Shannken .vfs_min_mount_data = 0,
2426d285189Shannken .vfs_mount = fdesc_mount,
2436d285189Shannken .vfs_start = fdesc_start,
2446d285189Shannken .vfs_unmount = fdesc_unmount,
2456d285189Shannken .vfs_root = fdesc_root,
2466d285189Shannken .vfs_quotactl = (void *)eopnotsupp,
2476d285189Shannken .vfs_statvfs = genfs_statvfs,
2486d285189Shannken .vfs_sync = fdesc_sync,
2496d285189Shannken .vfs_vget = fdesc_vget,
2503e04c969Shannken .vfs_loadvnode = fdesc_loadvnode,
2516d285189Shannken .vfs_fhtovp = (void *)eopnotsupp,
2526d285189Shannken .vfs_vptofh = (void *)eopnotsupp,
2536d285189Shannken .vfs_init = fdesc_init,
2546d285189Shannken .vfs_done = fdesc_done,
2556d285189Shannken .vfs_snapshot = (void *)eopnotsupp,
2566d285189Shannken .vfs_extattrctl = vfs_stdextattrctl,
257326db3aaShannken .vfs_suspendctl = genfs_suspendctl,
2586d285189Shannken .vfs_renamelock_enter = genfs_renamelock_enter,
2596d285189Shannken .vfs_renamelock_exit = genfs_renamelock_exit,
2606d285189Shannken .vfs_fsync = (void *)eopnotsupp,
2616d285189Shannken .vfs_opv_descs = fdesc_vnodeopv_descs
262e6035453Scgd };
263a1221b6dSrumble
2649120d451Spgoyette SYSCTL_SETUP(fdesc_sysctl_setup, "fdesc sysctl")
265a1221b6dSrumble {
266a1221b6dSrumble
2673a658204Spgoyette sysctl_createv(clog, 0, NULL, NULL,
26828f5ebd8Srumble CTLFLAG_PERMANENT,
26928f5ebd8Srumble CTLTYPE_NODE, "fdesc",
27028f5ebd8Srumble SYSCTL_DESCR("File-descriptor file system"),
27128f5ebd8Srumble NULL, 0, NULL, 0,
27228f5ebd8Srumble CTL_VFS, 7, CTL_EOL);
27328f5ebd8Srumble /*
27428f5ebd8Srumble * XXX the "7" above could be dynamic, thereby eliminating one
27528f5ebd8Srumble * more instance of the "number to vfs" mapping problem, but
27628f5ebd8Srumble * "7" is the order as taken from sys/mount.h
27728f5ebd8Srumble */
2789120d451Spgoyette }
2799120d451Spgoyette
2809120d451Spgoyette static int
fdesc_modcmd(modcmd_t cmd,void * arg)2819120d451Spgoyette fdesc_modcmd(modcmd_t cmd, void *arg)
2829120d451Spgoyette {
2839120d451Spgoyette int error;
2849120d451Spgoyette
2859120d451Spgoyette switch (cmd) {
2869120d451Spgoyette case MODULE_CMD_INIT:
2879120d451Spgoyette error = vfs_attach(&fdesc_vfsops);
2889120d451Spgoyette if (error != 0)
2899120d451Spgoyette break;
29028f5ebd8Srumble break;
291a1221b6dSrumble case MODULE_CMD_FINI:
29228f5ebd8Srumble error = vfs_detach(&fdesc_vfsops);
29328f5ebd8Srumble if (error != 0)
29428f5ebd8Srumble break;
29528f5ebd8Srumble break;
296a1221b6dSrumble default:
29728f5ebd8Srumble error = ENOTTY;
29828f5ebd8Srumble break;
299a1221b6dSrumble }
30028f5ebd8Srumble
30128f5ebd8Srumble return (error);
302a1221b6dSrumble }
303