xref: /netbsd-src/sys/miscfs/fdesc/fdesc_vfsops.c (revision 23bf88000cebbf7ff3c466a5b8ec755b87f03c6d)
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