1139776Simp/*- 222521Sdyson * Copyright (c) 1992, 1993, 1995 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from software donated to Berkeley by 61541Srgrimes * Jan-Simon Pendry. 71541Srgrimes * 81541Srgrimes * Redistribution and use in source and binary forms, with or without 91541Srgrimes * modification, are permitted provided that the following conditions 101541Srgrimes * are met: 111541Srgrimes * 1. Redistributions of source code must retain the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer. 131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer in the 151541Srgrimes * documentation and/or other materials provided with the distribution. 161541Srgrimes * 4. Neither the name of the University nor the names of its contributors 171541Srgrimes * may be used to endorse or promote products derived from this software 181541Srgrimes * without specific prior written permission. 191541Srgrimes * 201541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301541Srgrimes * SUCH DAMAGE. 311541Srgrimes * 321541Srgrimes * @(#)fdesc_vfsops.c 8.4 (Berkeley) 1/21/94 331541Srgrimes * 3450477Speter * $FreeBSD$ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes/* 381541Srgrimes * /dev/fd Filesystem 391541Srgrimes */ 401541Srgrimes 411541Srgrimes#include <sys/param.h> 421541Srgrimes#include <sys/systm.h> 4376166Smarkm#include <sys/filedesc.h> 442946Swollman#include <sys/kernel.h> 4576166Smarkm#include <sys/lock.h> 4689316Salfred#include <sys/mutex.h> 4776166Smarkm#include <sys/malloc.h> 4876166Smarkm#include <sys/mount.h> 491541Srgrimes#include <sys/proc.h> 50220400Strasz#include <sys/racct.h> 511541Srgrimes#include <sys/resourcevar.h> 521541Srgrimes#include <sys/vnode.h> 5376166Smarkm 5477031Sru#include <fs/fdescfs/fdesc.h> 551541Srgrimes 56151897Srwatsonstatic MALLOC_DEFINE(M_FDESCMNT, "fdesc_mount", "FDESC mount structure"); 5730354Sphk 58158611Skbyancstatic vfs_cmount_t fdesc_cmount; 59132902Sphkstatic vfs_mount_t fdesc_mount; 60116271Sphkstatic vfs_unmount_t fdesc_unmount; 61116271Sphkstatic vfs_statfs_t fdesc_statfs; 62141622Sphkstatic vfs_root_t fdesc_root; 63116271Sphk 641541Srgrimes/* 65158611Skbyanc * Compatibility shim for old mount(2) system call. 66158611Skbyanc */ 67158611Skbyancint 68230725Smckusickfdesc_cmount(struct mntarg *ma, void *data, uint64_t flags) 69158611Skbyanc{ 70158611Skbyanc return kernel_mount(ma, flags); 71158611Skbyanc} 72158611Skbyanc 73158611Skbyanc/* 741541Srgrimes * Mount the per-process file descriptors (/dev/fd) 751541Srgrimes */ 7612143Sphkstatic int 77191990Sattiliofdesc_mount(struct mount *mp) 781541Srgrimes{ 791541Srgrimes int error = 0; 801541Srgrimes struct fdescmount *fmp; 811541Srgrimes struct vnode *rvp; 821541Srgrimes 831541Srgrimes /* 841541Srgrimes * Update is a no-op 851541Srgrimes */ 86137478Sphk if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS)) 871541Srgrimes return (EOPNOTSUPP); 881541Srgrimes 89184205Sdes fmp = malloc(sizeof(struct fdescmount), 90111119Simp M_FDESCMNT, M_WAITOK); /* XXX */ 91179288Slulf 92179288Slulf /* 93179288Slulf * We need to initialize a few bits of our local mount point struct to 94179288Slulf * avoid confusion in allocvp. 95179288Slulf */ 96179288Slulf mp->mnt_data = (qaddr_t) fmp; 97179288Slulf fmp->flags = 0; 98191990Sattilio error = fdesc_allocvp(Froot, -1, FD_ROOT, mp, &rvp); 99179288Slulf if (error) { 100179288Slulf free(fmp, M_FDESCMNT); 101179288Slulf mp->mnt_data = 0; 102179288Slulf return (error); 103179288Slulf } 1041541Srgrimes rvp->v_type = VDIR; 105101308Sjeff rvp->v_vflag |= VV_ROOT; 1061541Srgrimes fmp->f_root = rvp; 107179288Slulf VOP_UNLOCK(rvp, 0); 1081541Srgrimes /* XXX -- don't mark as local to work around fts() problems */ 1091541Srgrimes /*mp->mnt_flag |= MNT_LOCAL;*/ 110179288Slulf MNT_ILOCK(mp); 111179288Slulf mp->mnt_kern_flag |= MNTK_MPSAFE; 112179288Slulf MNT_IUNLOCK(mp); 11322521Sdyson vfs_getnewfsid(mp); 1141541Srgrimes 115138483Sphk vfs_mountedfrom(mp, "fdescfs"); 1161541Srgrimes return (0); 1171541Srgrimes} 1181541Srgrimes 11912143Sphkstatic int 120191990Sattiliofdesc_unmount(mp, mntflags) 1211541Srgrimes struct mount *mp; 1221541Srgrimes int mntflags; 1231541Srgrimes{ 124179288Slulf struct fdescmount *fmp; 125179288Slulf caddr_t data; 1261541Srgrimes int error; 1271541Srgrimes int flags = 0; 1281541Srgrimes 129179288Slulf fmp = (struct fdescmount *)mp->mnt_data; 130179288Slulf if (mntflags & MNT_FORCE) { 131179288Slulf /* The hash mutex protects the private mount flags. */ 132179288Slulf mtx_lock(&fdesc_hashmtx); 133179288Slulf fmp->flags |= FMNT_UNMOUNTF; 134179288Slulf mtx_unlock(&fdesc_hashmtx); 1351541Srgrimes flags |= FORCECLOSE; 136179288Slulf } 1371541Srgrimes 1381541Srgrimes /* 1391541Srgrimes * Clear out buffer cache. I don't think we 1401541Srgrimes * ever get anything cached at this level at the 1411541Srgrimes * moment, but who knows... 14276688Siedowse * 14376688Siedowse * There is 1 extra root vnode reference corresponding 14476688Siedowse * to f_root. 1451541Srgrimes */ 146191990Sattilio if ((error = vflush(mp, 1, flags, curthread)) != 0) 1471541Srgrimes return (error); 1481541Srgrimes 1491541Srgrimes /* 150179288Slulf * Finally, throw away the fdescmount structure. Hold the hashmtx to 151179288Slulf * protect the fdescmount structure. 1521541Srgrimes */ 153179288Slulf mtx_lock(&fdesc_hashmtx); 154179288Slulf data = mp->mnt_data; 1551541Srgrimes mp->mnt_data = 0; 156179288Slulf mtx_unlock(&fdesc_hashmtx); 157179288Slulf free(data, M_FDESCMNT); /* XXX */ 1581541Srgrimes 1591541Srgrimes return (0); 1601541Srgrimes} 1611541Srgrimes 162141622Sphkstatic int 163191990Sattiliofdesc_root(mp, flags, vpp) 1641541Srgrimes struct mount *mp; 165144058Sjeff int flags; 1661541Srgrimes struct vnode **vpp; 1671541Srgrimes{ 1681541Srgrimes struct vnode *vp; 1691541Srgrimes 1701541Srgrimes /* 1711541Srgrimes * Return locked reference to root. 1721541Srgrimes */ 1731541Srgrimes vp = VFSTOFDESC(mp)->f_root; 174191990Sattilio vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread); 1751541Srgrimes *vpp = vp; 1761541Srgrimes return (0); 1771541Srgrimes} 1781541Srgrimes 17912143Sphkstatic int 180191990Sattiliofdesc_statfs(mp, sbp) 1811541Srgrimes struct mount *mp; 1821541Srgrimes struct statfs *sbp; 183191990Sattilio{ 18483366Sjulian struct thread *td; 1851541Srgrimes struct filedesc *fdp; 1861541Srgrimes int lim; 1871541Srgrimes int i; 1881541Srgrimes int last; 1891541Srgrimes int freefd; 190220400Strasz uint64_t limit; 1911541Srgrimes 192191990Sattilio td = curthread; 193191990Sattilio 1941541Srgrimes /* 1951541Srgrimes * Compute number of free file descriptors. 1961541Srgrimes * [ Strange results will ensue if the open file 1971541Srgrimes * limit is ever reduced below the current number 1981541Srgrimes * of open files... ] 1991541Srgrimes */ 200125454Sjhb PROC_LOCK(td->td_proc); 201125454Sjhb lim = lim_cur(td->td_proc, RLIMIT_NOFILE); 202125454Sjhb PROC_UNLOCK(td->td_proc); 20383366Sjulian fdp = td->td_proc->p_fd; 204168355Srwatson FILEDESC_SLOCK(fdp); 205220400Strasz limit = racct_get_limit(td->td_proc, RACCT_NOFILE); 206220400Strasz if (lim > limit) 207220400Strasz lim = limit; 2081541Srgrimes last = min(fdp->fd_nfiles, lim); 2091541Srgrimes freefd = 0; 2101541Srgrimes for (i = fdp->fd_freefile; i < last; i++) 2111541Srgrimes if (fdp->fd_ofiles[i] == NULL) 2121541Srgrimes freefd++; 2131541Srgrimes 2141541Srgrimes /* 2151541Srgrimes * Adjust for the fact that the fdesc array may not 2161541Srgrimes * have been fully allocated yet. 2171541Srgrimes */ 2181541Srgrimes if (fdp->fd_nfiles < lim) 2191541Srgrimes freefd += (lim - fdp->fd_nfiles); 220168355Srwatson FILEDESC_SUNLOCK(fdp); 2211541Srgrimes 2221541Srgrimes sbp->f_flags = 0; 2231541Srgrimes sbp->f_bsize = DEV_BSIZE; 2241541Srgrimes sbp->f_iosize = DEV_BSIZE; 2251541Srgrimes sbp->f_blocks = 2; /* 1K to keep df happy */ 2261541Srgrimes sbp->f_bfree = 0; 2271541Srgrimes sbp->f_bavail = 0; 2281541Srgrimes sbp->f_files = lim + 1; /* Allow for "." */ 2291541Srgrimes sbp->f_ffree = freefd; /* See comments above */ 2301541Srgrimes return (0); 2311541Srgrimes} 2321541Srgrimes 23312143Sphkstatic struct vfsops fdesc_vfsops = { 234158611Skbyanc .vfs_cmount = fdesc_cmount, 235116271Sphk .vfs_init = fdesc_init, 236132902Sphk .vfs_mount = fdesc_mount, 237116271Sphk .vfs_root = fdesc_root, 238116271Sphk .vfs_statfs = fdesc_statfs, 239179288Slulf .vfs_uninit = fdesc_uninit, 240116271Sphk .vfs_unmount = fdesc_unmount, 2411541Srgrimes}; 2422946Swollman 24377133SruVFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC); 244