Home | History | Annotate | Line # | Download | only in fdesc
      1 /*	$NetBSD: fdesc_vfsops.c,v 1.96 2020/04/13 19:23:18 ad Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1992, 1993, 1995
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This code is derived from software donated to Berkeley by
      8  * Jan-Simon Pendry.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. Neither the name of the University nor the names of its contributors
     19  *    may be used to endorse or promote products derived from this software
     20  *    without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  *
     34  *	@(#)fdesc_vfsops.c	8.10 (Berkeley) 5/14/95
     35  *
     36  * #Id: fdesc_vfsops.c,v 1.9 1993/04/06 15:28:33 jsp Exp #
     37  */
     38 
     39 /*
     40  * /dev/fd Filesystem
     41  */
     42 
     43 #include <sys/cdefs.h>
     44 __KERNEL_RCSID(0, "$NetBSD: fdesc_vfsops.c,v 1.96 2020/04/13 19:23:18 ad Exp $");
     45 
     46 #if defined(_KERNEL_OPT)
     47 #include "opt_compat_netbsd.h"
     48 #endif
     49 
     50 #include <sys/param.h>
     51 #include <sys/systm.h>
     52 #include <sys/sysctl.h>
     53 #include <sys/time.h>
     54 #include <sys/proc.h>
     55 #include <sys/resourcevar.h>
     56 #include <sys/filedesc.h>
     57 #include <sys/vnode.h>
     58 #include <sys/mount.h>
     59 #include <sys/dirent.h>
     60 #include <sys/namei.h>
     61 #include <sys/kauth.h>
     62 #include <sys/module.h>
     63 
     64 #include <miscfs/genfs/genfs.h>
     65 #include <miscfs/fdesc/fdesc.h>
     66 
     67 MODULE(MODULE_CLASS_VFS, fdesc, NULL);
     68 
     69 VFS_PROTOS(fdesc);
     70 
     71 /*
     72  * Mount the per-process file descriptors (/dev/fd)
     73  */
     74 int
     75 fdesc_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
     76 {
     77 	struct lwp *l = curlwp;
     78 	int error = 0, ix;
     79 	struct vnode *rvp;
     80 
     81 	if (mp->mnt_flag & MNT_GETARGS) {
     82 		*data_len = 0;
     83 		return 0;
     84 	}
     85 	/*
     86 	 * Update is a no-op
     87 	 */
     88 	if (mp->mnt_flag & MNT_UPDATE)
     89 		return (EOPNOTSUPP);
     90 
     91 	ix = FD_ROOT;
     92 	error = vcache_get(mp, &ix, sizeof(ix), &rvp);
     93 	if (error)
     94 		return error;
     95 
     96 	mp->mnt_stat.f_namemax = FDESC_MAXNAMLEN;
     97 	mp->mnt_flag |= MNT_LOCAL;
     98 	mp->mnt_data = rvp;
     99 	vfs_getnewfsid(mp);
    100 
    101 	error = set_statvfs_info(path, UIO_USERSPACE, "fdesc", UIO_SYSSPACE,
    102 	    mp->mnt_op->vfs_name, mp, l);
    103 	return error;
    104 }
    105 
    106 int
    107 fdesc_start(struct mount *mp, int flags)
    108 {
    109 	return (0);
    110 }
    111 
    112 int
    113 fdesc_unmount(struct mount *mp, int mntflags)
    114 {
    115 	int error;
    116 	int flags = 0;
    117 	struct vnode *rtvp = mp->mnt_data;
    118 
    119 	if (mntflags & MNT_FORCE)
    120 		flags |= FORCECLOSE;
    121 
    122 	if (vrefcnt(rtvp) > 1 && (mntflags & MNT_FORCE) == 0)
    123 		return (EBUSY);
    124 	if ((error = vflush(mp, rtvp, flags)) != 0)
    125 		return (error);
    126 
    127 	/*
    128 	 * Blow it away for future re-use
    129 	 */
    130 	vgone(rtvp);
    131 	mp->mnt_data = NULL;
    132 
    133 	return (0);
    134 }
    135 
    136 int
    137 fdesc_root(struct mount *mp, int lktype, struct vnode **vpp)
    138 {
    139 	struct vnode *vp;
    140 
    141 	/*
    142 	 * Return locked reference to root.
    143 	 */
    144 	vp = mp->mnt_data;
    145 	vref(vp);
    146 	vn_lock(vp, lktype | LK_RETRY);
    147 	*vpp = vp;
    148 	return (0);
    149 }
    150 
    151 /*ARGSUSED*/
    152 int
    153 fdesc_sync(struct mount *mp, int waitfor,
    154     kauth_cred_t uc)
    155 {
    156 
    157 	return (0);
    158 }
    159 
    160 /*
    161  * Fdesc flat namespace lookup.
    162  * Currently unsupported.
    163  */
    164 int
    165 fdesc_vget(struct mount *mp, ino_t ino, int lktype,
    166     struct vnode **vpp)
    167 {
    168 
    169 	return (EOPNOTSUPP);
    170 }
    171 
    172 int
    173 fdesc_loadvnode(struct mount *mp, struct vnode *vp,
    174     const void *key, size_t key_len, const void **new_key)
    175 {
    176 	int ix;
    177 	struct fdescnode *fd;
    178 
    179 	KASSERT(key_len == sizeof(ix));
    180 	memcpy(&ix, key, key_len);
    181 
    182 	fd = kmem_alloc(sizeof(struct fdescnode), KM_SLEEP);
    183 	fd->fd_fd = -1;
    184 	fd->fd_link = NULL;
    185 	fd->fd_ix = ix;
    186 	fd->fd_vnode = vp;
    187 	vp->v_tag = VT_FDESC;
    188 	vp->v_op = fdesc_vnodeop_p;
    189 	vp->v_data = fd;
    190 	switch (ix) {
    191 	case FD_ROOT:
    192 		fd->fd_type = Froot;
    193 		vp->v_type = VDIR;
    194 		vp->v_vflag |= VV_ROOT;
    195 		break;
    196 	case FD_DEVFD:
    197 		fd->fd_type = Fdevfd;
    198 		vp->v_type = VDIR;
    199 		break;
    200 	case FD_CTTY:
    201 		fd->fd_type = Fctty;
    202 		vp->v_type = VCHR;
    203 		break;
    204 	case FD_STDIN:
    205 		fd->fd_type = Flink;
    206 		fd->fd_link = "fd/0";
    207 		vp->v_type = VLNK;
    208 		break;
    209 	case FD_STDOUT:
    210 		fd->fd_type = Flink;
    211 		fd->fd_link = "fd/1";
    212 		vp->v_type = VLNK;
    213 		break;
    214 	case FD_STDERR:
    215 		fd->fd_type = Flink;
    216 		fd->fd_link = "fd/2";
    217 		vp->v_type = VLNK;
    218 		break;
    219 	default:
    220 		KASSERT(ix >= FD_DESC);
    221 		fd->fd_type = Fdesc;
    222 		fd->fd_fd = ix - FD_DESC;
    223 		vp->v_type = VNON;
    224 		break;
    225 	}
    226 	uvm_vnp_setsize(vp, 0);
    227 	*new_key = &fd->fd_ix;
    228 
    229 	return 0;
    230 }
    231 
    232 extern const struct vnodeopv_desc fdesc_vnodeop_opv_desc;
    233 
    234 const struct vnodeopv_desc * const fdesc_vnodeopv_descs[] = {
    235 	&fdesc_vnodeop_opv_desc,
    236 	NULL,
    237 };
    238 
    239 struct vfsops fdesc_vfsops = {
    240 	.vfs_name = MOUNT_FDESC,
    241 	.vfs_min_mount_data = 0,
    242 	.vfs_mount = fdesc_mount,
    243 	.vfs_start = fdesc_start,
    244 	.vfs_unmount = fdesc_unmount,
    245 	.vfs_root = fdesc_root,
    246 	.vfs_quotactl = (void *)eopnotsupp,
    247 	.vfs_statvfs = genfs_statvfs,
    248 	.vfs_sync = fdesc_sync,
    249 	.vfs_vget = fdesc_vget,
    250 	.vfs_loadvnode = fdesc_loadvnode,
    251 	.vfs_fhtovp = (void *)eopnotsupp,
    252 	.vfs_vptofh = (void *)eopnotsupp,
    253 	.vfs_init = fdesc_init,
    254 	.vfs_done = fdesc_done,
    255 	.vfs_snapshot = (void *)eopnotsupp,
    256 	.vfs_extattrctl = vfs_stdextattrctl,
    257 	.vfs_suspendctl = genfs_suspendctl,
    258 	.vfs_renamelock_enter = genfs_renamelock_enter,
    259 	.vfs_renamelock_exit = genfs_renamelock_exit,
    260 	.vfs_fsync = (void *)eopnotsupp,
    261 	.vfs_opv_descs = fdesc_vnodeopv_descs
    262 };
    263 
    264 SYSCTL_SETUP(fdesc_sysctl_setup, "fdesc sysctl")
    265 {
    266 
    267 		sysctl_createv(clog, 0, NULL, NULL,
    268 			       CTLFLAG_PERMANENT,
    269 			       CTLTYPE_NODE, "fdesc",
    270 			       SYSCTL_DESCR("File-descriptor file system"),
    271 			       NULL, 0, NULL, 0,
    272 			       CTL_VFS, 7, CTL_EOL);
    273 		/*
    274 		 * XXX the "7" above could be dynamic, thereby eliminating one
    275 		 * more instance of the "number to vfs" mapping problem, but
    276 		 * "7" is the order as taken from sys/mount.h
    277 		 */
    278 }
    279 
    280 static int
    281 fdesc_modcmd(modcmd_t cmd, void *arg)
    282 {
    283 	int error;
    284 
    285 	switch (cmd) {
    286 	case MODULE_CMD_INIT:
    287 		error = vfs_attach(&fdesc_vfsops);
    288 		if (error != 0)
    289 			break;
    290 		break;
    291 	case MODULE_CMD_FINI:
    292 		error = vfs_detach(&fdesc_vfsops);
    293 		if (error != 0)
    294 			break;
    295 		break;
    296 	default:
    297 		error = ENOTTY;
    298 		break;
    299 	}
    300 
    301 	return (error);
    302 }
    303