]> git.saurik.com Git - apple/xnu.git/blob - bsd/miscfs/fdesc/fdesc_vfsops.c
xnu-1228.5.18.tar.gz
[apple/xnu.git] / bsd / miscfs / fdesc / fdesc_vfsops.c
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 */
87 static int
88 fdesc_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
122 static int
123 fdesc_start(__unused struct mount *mp, __unused int flags, __unused vfs_context_t context)
124 {
125 return (0);
126 }
127
128 static int
129 fdesc_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
163 int
164 fdesc_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 */
181 int
182 fdesc_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
226 static int
227 fdesc_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
279 static int
280 fdesc_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
291 struct 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 };