fdesc_vfsops.c revision 242833
198524Sfenner/*- 298524Sfenner * Copyright (c) 1992, 1993, 1995 398524Sfenner * The Regents of the University of California. All rights reserved. 498524Sfenner * 598524Sfenner * This code is derived from software donated to Berkeley by 698524Sfenner * Jan-Simon Pendry. 798524Sfenner * 898524Sfenner * Redistribution and use in source and binary forms, with or without 998524Sfenner * modification, are permitted provided that the following conditions 1098524Sfenner * are met: 1198524Sfenner * 1. Redistributions of source code must retain the above copyright 1298524Sfenner * notice, this list of conditions and the following disclaimer. 1398524Sfenner * 2. Redistributions in binary form must reproduce the above copyright 1498524Sfenner * notice, this list of conditions and the following disclaimer in the 1598524Sfenner * documentation and/or other materials provided with the distribution. 1698524Sfenner * 4. Neither the name of the University nor the names of its contributors 1798524Sfenner * may be used to endorse or promote products derived from this software 1898524Sfenner * without specific prior written permission. 1998524Sfenner * 2098524Sfenner * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2198524Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2298524Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2398524Sfenner * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2498524Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2598524Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26127668Sbms * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27190207Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2898524Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2998524Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3098524Sfenner * SUCH DAMAGE. 3198524Sfenner * 3298524Sfenner * @(#)fdesc_vfsops.c 8.4 (Berkeley) 1/21/94 3398524Sfenner * 34127668Sbms * $FreeBSD: head/sys/fs/fdescfs/fdesc_vfsops.c 242833 2012-11-09 18:02:25Z attilio $ 35127668Sbms */ 3698524Sfenner 3798524Sfenner/* 3898524Sfenner * /dev/fd Filesystem 39127668Sbms */ 4098524Sfenner 4198524Sfenner#include <sys/param.h> 4298524Sfenner#include <sys/systm.h> 4398524Sfenner#include <sys/filedesc.h> 4498524Sfenner#include <sys/kernel.h> 4598524Sfenner#include <sys/lock.h> 4698524Sfenner#include <sys/mutex.h> 4798524Sfenner#include <sys/malloc.h> 4898524Sfenner#include <sys/mount.h> 49127668Sbms#include <sys/proc.h> 5098524Sfenner#include <sys/racct.h> 5198524Sfenner#include <sys/resourcevar.h> 5298524Sfenner#include <sys/vnode.h> 5398524Sfenner 5498524Sfenner#include <fs/fdescfs/fdesc.h> 5598524Sfenner 5698524Sfennerstatic MALLOC_DEFINE(M_FDESCMNT, "fdesc_mount", "FDESC mount structure"); 5798524Sfenner 5898524Sfennerstatic vfs_cmount_t fdesc_cmount; 5998524Sfennerstatic vfs_mount_t fdesc_mount; 6098524Sfennerstatic vfs_unmount_t fdesc_unmount; 6198524Sfennerstatic vfs_statfs_t fdesc_statfs; 6298524Sfennerstatic vfs_root_t fdesc_root; 6398524Sfenner 6498524Sfenner/* 6598524Sfenner * Compatibility shim for old mount(2) system call. 6698524Sfenner */ 6798524Sfennerint 6898524Sfennerfdesc_cmount(struct mntarg *ma, void *data, uint64_t flags) 69127668Sbms{ 7098524Sfenner return kernel_mount(ma, flags); 7198524Sfenner} 7298524Sfenner 7398524Sfenner/* 7498524Sfenner * Mount the per-process file descriptors (/dev/fd) 7598524Sfenner */ 7698524Sfennerstatic int 7798524Sfennerfdesc_mount(struct mount *mp) 7898524Sfenner{ 7998524Sfenner int error = 0; 8098524Sfenner struct fdescmount *fmp; 8198524Sfenner struct vnode *rvp; 8298524Sfenner 8398524Sfenner /* 8498524Sfenner * Update is a no-op 8598524Sfenner */ 8698524Sfenner if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS)) 8798524Sfenner return (EOPNOTSUPP); 8898524Sfenner 8998524Sfenner fmp = malloc(sizeof(struct fdescmount), 9098524Sfenner M_FDESCMNT, M_WAITOK); /* XXX */ 9198524Sfenner 9298524Sfenner /* 9398524Sfenner * We need to initialize a few bits of our local mount point struct to 9498524Sfenner * avoid confusion in allocvp. 9598524Sfenner */ 9698524Sfenner mp->mnt_data = (qaddr_t) fmp; 9798524Sfenner fmp->flags = 0; 9898524Sfenner error = fdesc_allocvp(Froot, -1, FD_ROOT, mp, &rvp); 9998524Sfenner if (error) { 10098524Sfenner free(fmp, M_FDESCMNT); 10198524Sfenner mp->mnt_data = NULL; 10298524Sfenner return (error); 10398524Sfenner } 10498524Sfenner rvp->v_type = VDIR; 10598524Sfenner rvp->v_vflag |= VV_ROOT; 10698524Sfenner fmp->f_root = rvp; 10798524Sfenner VOP_UNLOCK(rvp, 0); 10898524Sfenner /* XXX -- don't mark as local to work around fts() problems */ 10998524Sfenner /*mp->mnt_flag |= MNT_LOCAL;*/ 11098524Sfenner vfs_getnewfsid(mp); 11198524Sfenner 11298524Sfenner vfs_mountedfrom(mp, "fdescfs"); 11398524Sfenner return (0); 11498524Sfenner} 11598524Sfenner 11698524Sfennerstatic int 11798524Sfennerfdesc_unmount(mp, mntflags) 11898524Sfenner struct mount *mp; 11998524Sfenner int mntflags; 12098524Sfenner{ 12198524Sfenner struct fdescmount *fmp; 12298524Sfenner caddr_t data; 12398524Sfenner int error; 12498524Sfenner int flags = 0; 12598524Sfenner 12698524Sfenner fmp = (struct fdescmount *)mp->mnt_data; 12798524Sfenner if (mntflags & MNT_FORCE) { 12898524Sfenner /* The hash mutex protects the private mount flags. */ 12998524Sfenner mtx_lock(&fdesc_hashmtx); 13098524Sfenner fmp->flags |= FMNT_UNMOUNTF; 13198524Sfenner mtx_unlock(&fdesc_hashmtx); 13298524Sfenner flags |= FORCECLOSE; 13398524Sfenner } 13498524Sfenner 13598524Sfenner /* 13698524Sfenner * Clear out buffer cache. I don't think we 13798524Sfenner * ever get anything cached at this level at the 13898524Sfenner * moment, but who knows... 13998524Sfenner * 14098524Sfenner * There is 1 extra root vnode reference corresponding 14198524Sfenner * to f_root. 14298524Sfenner */ 14398524Sfenner if ((error = vflush(mp, 1, flags, curthread)) != 0) 14498524Sfenner return (error); 14598524Sfenner 14698524Sfenner /* 14798524Sfenner * Finally, throw away the fdescmount structure. Hold the hashmtx to 14898524Sfenner * protect the fdescmount structure. 14998524Sfenner */ 15098524Sfenner mtx_lock(&fdesc_hashmtx); 15198524Sfenner data = mp->mnt_data; 15298524Sfenner mp->mnt_data = NULL; 15398524Sfenner mtx_unlock(&fdesc_hashmtx); 15498524Sfenner free(data, M_FDESCMNT); /* XXX */ 15598524Sfenner 15698524Sfenner return (0); 15798524Sfenner} 15898524Sfenner 15998524Sfennerstatic int 16098524Sfennerfdesc_root(mp, flags, vpp) 16198524Sfenner struct mount *mp; 16298524Sfenner int flags; 16398524Sfenner struct vnode **vpp; 16498524Sfenner{ 16598524Sfenner struct vnode *vp; 16698524Sfenner 16798524Sfenner /* 16898524Sfenner * Return locked reference to root. 16998524Sfenner */ 17098524Sfenner vp = VFSTOFDESC(mp)->f_root; 17198524Sfenner vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread); 17298524Sfenner *vpp = vp; 17398524Sfenner return (0); 17498524Sfenner} 17598524Sfenner 17698524Sfennerstatic int 17798524Sfennerfdesc_statfs(mp, sbp) 17898524Sfenner struct mount *mp; 179127668Sbms struct statfs *sbp; 180127668Sbms{ 18198524Sfenner struct thread *td; 18298524Sfenner struct filedesc *fdp; 18398524Sfenner int lim; 18498524Sfenner int i; 18598524Sfenner int last; 18698524Sfenner int freefd; 18798524Sfenner uint64_t limit; 18898524Sfenner 18998524Sfenner td = curthread; 19098524Sfenner 19198524Sfenner /* 19298524Sfenner * Compute number of free file descriptors. 19398524Sfenner * [ Strange results will ensue if the open file 19498524Sfenner * limit is ever reduced below the current number 19598524Sfenner * of open files... ] 19698524Sfenner */ 19798524Sfenner PROC_LOCK(td->td_proc); 19898524Sfenner lim = lim_cur(td->td_proc, RLIMIT_NOFILE); 19998524Sfenner PROC_UNLOCK(td->td_proc); 20098524Sfenner fdp = td->td_proc->p_fd; 20198524Sfenner FILEDESC_SLOCK(fdp); 20298524Sfenner limit = racct_get_limit(td->td_proc, RACCT_NOFILE); 20398524Sfenner if (lim > limit) 20498524Sfenner lim = limit; 20598524Sfenner last = min(fdp->fd_nfiles, lim); 20698524Sfenner freefd = 0; 20798524Sfenner for (i = fdp->fd_freefile; i < last; i++) 20898524Sfenner if (fdp->fd_ofiles[i] == NULL) 20998524Sfenner freefd++; 21098524Sfenner 21198524Sfenner /* 21298524Sfenner * Adjust for the fact that the fdesc array may not 21398524Sfenner * have been fully allocated yet. 21498524Sfenner */ 21598524Sfenner if (fdp->fd_nfiles < lim) 21698524Sfenner freefd += (lim - fdp->fd_nfiles); 21798524Sfenner FILEDESC_SUNLOCK(fdp); 21898524Sfenner 21998524Sfenner sbp->f_flags = 0; 22098524Sfenner sbp->f_bsize = DEV_BSIZE; 22198524Sfenner sbp->f_iosize = DEV_BSIZE; 22298524Sfenner sbp->f_blocks = 2; /* 1K to keep df happy */ 22398524Sfenner sbp->f_bfree = 0; 22498524Sfenner sbp->f_bavail = 0; 22598524Sfenner sbp->f_files = lim + 1; /* Allow for "." */ 22698524Sfenner sbp->f_ffree = freefd; /* See comments above */ 22798524Sfenner return (0); 22898524Sfenner} 22998524Sfenner 23098524Sfennerstatic struct vfsops fdesc_vfsops = { 23198524Sfenner .vfs_cmount = fdesc_cmount, 23298524Sfenner .vfs_init = fdesc_init, 23398524Sfenner .vfs_mount = fdesc_mount, 23498524Sfenner .vfs_root = fdesc_root, 23598524Sfenner .vfs_statfs = fdesc_statfs, 23698524Sfenner .vfs_uninit = fdesc_uninit, 23798524Sfenner .vfs_unmount = fdesc_unmount, 23898524Sfenner}; 239127668Sbms 24098524SfennerVFS_SET(fdesc_vfsops, fdescfs, VFCF_SYNTHETIC); 24198524Sfenner