1/* 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ 29/* 30 * Copyright (c) 1992, 1993, 1995 31 * The Regents of the University of California. All rights reserved. 32 * 33 * This code is derived from software donated to Berkeley by 34 * Jan-Simon Pendry. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)fdesc_vfsops.c 8.10 (Berkeley) 5/14/95 65 * 66 */ 67/* 68* /dev/fd Filesystem 69 */ 70 71#include <sys/param.h> 72#include <sys/systm.h> 73#include <sys/time.h> 74#include <sys/types.h> 75#include <sys/proc_internal.h> 76#include <sys/resourcevar.h> 77#include <sys/filedesc.h> 78#include <sys/vnode.h> 79#include <sys/mount_internal.h> 80#include <sys/namei.h> 81#include <sys/malloc.h> 82#include <miscfs/fdesc/fdesc.h> 83 84/* 85 * Mount the per-process file descriptors (/dev/fd) 86 */ 87static int 88fdesc_mount(struct mount *mp, __unused vnode_t devvp, __unused user_addr_t data, __unused vfs_context_t context) 89{ 90 int error = 0; 91 struct fdescmount *fmp; 92 struct vnode *rvp; 93 94 /* 95 * Update is a no-op 96 */ 97 if (mp->mnt_flag & MNT_UPDATE) 98 return (ENOTSUP); 99 100 error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp, VDIR); 101 if (error) 102 return (error); 103 104 MALLOC(fmp, struct fdescmount *, sizeof(struct fdescmount), 105 M_UFSMNT, M_WAITOK); /* XXX */ 106 107 vnode_setnoflush(rvp); 108 vnode_ref(rvp); 109 vnode_put(rvp); 110 111 fmp->f_root = rvp; 112 /* XXX -- don't mark as local to work around fts() problems */ 113 /*mp->mnt_flag |= MNT_LOCAL;*/ 114 mp->mnt_data = (qaddr_t) fmp; 115 vfs_getnewfsid(mp); 116 117 bzero(mp->mnt_vfsstat.f_mntfromname, MAXPATHLEN); 118 bcopy("fdesc", mp->mnt_vfsstat.f_mntfromname, sizeof("fdesc")); 119 return (0); 120} 121 122static int 123fdesc_start(__unused struct mount *mp, __unused int flags, __unused vfs_context_t context) 124{ 125 return (0); 126} 127 128static int 129fdesc_unmount(struct mount *mp, int mntflags, __unused vfs_context_t context) 130{ 131 int error; 132 int flags = 0; 133 int force = 0; 134 struct vnode *rvp = VFSTOFDESC(mp)->f_root; 135 136 if (mntflags & MNT_FORCE) { 137 flags |= FORCECLOSE; 138 force = 1; 139 } 140 141 if ( vnode_isinuse(rvp, 1) && !force ) 142 return (EBUSY); 143 if ( (error = vflush(mp, rvp, flags|SKIPSYSTEM)) && !force ) 144 return (error); 145 146 /* 147 * And mark for recycle after we drop its reference; it away for future re-use 148 */ 149 vnode_recycle(rvp); 150 /* 151 * Release reference on underlying root vnode 152 */ 153 vnode_rele(rvp); 154 /* 155 * Finally, throw away the fdescmount structure 156 */ 157 _FREE(mp->mnt_data, M_UFSMNT); /* XXX */ 158 mp->mnt_data = NULL; 159 160 return (0); 161} 162 163int 164fdesc_root(struct mount *mp, struct vnode **vpp, __unused vfs_context_t context) 165{ 166 struct vnode *vp; 167 168 /* 169 * Return locked reference to root. 170 */ 171 vp = VFSTOFDESC(mp)->f_root; 172 vnode_get(vp); 173 *vpp = vp; 174 return (0); 175} 176 177#if 0 178/* 179 * XXX commented out in mount.h 180 */ 181int 182fdesc_statfs(__unused struct mount *mp, struct vfsstatfs *sbp, vfs_context_t context) 183{ 184 proc_t p = vfs_context_proc(context); 185 struct filedesc *fdp; 186 int lim; 187 int i; 188 int last; 189 int freefd; 190 191 /* 192 * Compute number of free file descriptors. 193 * [ Strange results will ensue if the open file 194 * limit is ever reduced below the current number 195 * of open files... ] 196 */ 197 lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur; 198 fdp = p->p_fd; 199 last = min(fdp->fd_nfiles, lim); 200 freefd = 0; 201 for (i = fdp->fd_freefile; i < last; i++) 202 if (fdp->fd_ofiles[i] == NULL && 203 !(fdp->fd_ofileflags[i] & UF_RESERVED)) 204 freefd++; 205 206 /* 207 * Adjust for the fact that the fdesc array may not 208 * have been fully allocated yet. 209 */ 210 if (fdp->fd_nfiles < lim) 211 freefd += (lim - fdp->fd_nfiles); 212 213 sbp->f_flags = 0; 214 sbp->f_bsize = DEV_BSIZE; 215 sbp->f_iosize = DEV_BSIZE; 216 sbp->f_blocks = (uint64_t)2; /* 1K to keep df happy */ 217 sbp->f_bfree = 0; 218 sbp->f_bavail = 0; 219 sbp->f_files = (uint64_t)((unsigned long)(lim + 1)); /* Allow for "." */ 220 sbp->f_ffree = (uint64_t)((unsigned long)freefd); /* See comments above */ 221 222 return (0); 223} 224#endif /* 0 */ 225 226static int 227fdesc_vfs_getattr(__unused mount_t mp, struct vfs_attr *fsap, vfs_context_t context) 228{ 229 VFSATTR_RETURN(fsap, f_bsize, DEV_BSIZE); 230 VFSATTR_RETURN(fsap, f_iosize, DEV_BSIZE); 231 VFSATTR_RETURN(fsap, f_blocks, 2); 232 VFSATTR_RETURN(fsap, f_bfree, 0); 233 VFSATTR_RETURN(fsap, f_bavail, 0); 234 VFSATTR_RETURN(fsap, f_fssubtype, 0); 235 236 if (VFSATTR_IS_ACTIVE(fsap, f_objcount) || 237 VFSATTR_IS_ACTIVE(fsap, f_maxobjcount) || 238 VFSATTR_IS_ACTIVE(fsap, f_files) || 239 VFSATTR_IS_ACTIVE(fsap, f_ffree)) 240 { 241 proc_t p = vfs_context_proc(context); 242 struct filedesc *fdp; 243 int lim; 244 int i; 245 int last; 246 int freefd; 247 248 /* 249 * Compute number of free file descriptors. 250 * [ Strange results will ensue if the open file 251 * limit is ever reduced below the current number 252 * of open files... ] 253 */ 254 lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur; 255 fdp = p->p_fd; 256 last = min(fdp->fd_nfiles, lim); 257 freefd = 0; 258 for (i = fdp->fd_freefile; i < last; i++) 259 if (fdp->fd_ofiles[i] == NULL && 260 !(fdp->fd_ofileflags[i] & UF_RESERVED)) 261 freefd++; 262 263 /* 264 * Adjust for the fact that the fdesc array may not 265 * have been fully allocated yet. 266 */ 267 if (fdp->fd_nfiles < lim) 268 freefd += (lim - fdp->fd_nfiles); 269 270 VFSATTR_RETURN(fsap, f_objcount, lim+1); 271 VFSATTR_RETURN(fsap, f_maxobjcount, lim+1); 272 VFSATTR_RETURN(fsap, f_files, lim+1); 273 VFSATTR_RETURN(fsap, f_ffree, freefd); 274 } 275 276 return 0; 277} 278 279static int 280fdesc_sync(__unused struct mount *mp, __unused int waitfor, __unused vfs_context_t context) 281{ 282 283 return (0); 284} 285 286#define fdesc_fhtovp (int (*) (mount_t, int, unsigned char *, vnode_t *, vfs_context_t))eopnotsupp 287#define fdesc_sysctl (int (*) (int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, vfs_context_t))eopnotsupp 288#define fdesc_vget (int (*) (mount_t, ino64_t, vnode_t *, vfs_context_t))eopnotsupp 289#define fdesc_vptofh (int (*) (vnode_t, int *, unsigned char *, vfs_context_t))eopnotsupp 290 291struct vfsops fdesc_vfsops = { 292 fdesc_mount, 293 fdesc_start, 294 fdesc_unmount, 295 fdesc_root, 296 NULL, /* quotactl */ 297 fdesc_vfs_getattr, 298/* fdesc_statfs, XXX commented out in mount.h */ 299 fdesc_sync, 300 fdesc_vget, 301 fdesc_fhtovp, 302 fdesc_vptofh, 303 fdesc_init, 304 fdesc_sysctl, 305 NULL, 306 {NULL} 307}; 308