]> git.saurik.com Git - apple/xnu.git/blob - bsd/miscfs/nullfs/null_vfsops.c
a103c6d4879003a048f316af4c0097c5db0c1628
[apple/xnu.git] / bsd / miscfs / nullfs / null_vfsops.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
31 /*
32 * Copyright (c) 1992, 1993
33 * The Regents of the University of California. All rights reserved.
34 *
35 * This code is derived from software donated to Berkeley by
36 * Jan-Simon Pendry.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * @(#)null_vfsops.c 8.7 (Berkeley) 5/14/95
67 *
68 * @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92
69 */
70
71 /*
72 * Null Layer
73 * (See null_vnops.c for a description of what this does.)
74 */
75
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/proc.h>
79 #include <sys/kauth.h>
80 #include <sys/time.h>
81 #include <sys/types.h>
82 #include <sys/vnode.h>
83 #include <sys/mount_internal.h>
84 #include <sys/namei.h>
85 #include <sys/malloc.h>
86 #include <miscfs/nullfs/null.h>
87
88 /*
89 * Mount null layer
90 */
91 static int
92 nullfs_mount(mp, devvp, data, context)
93 struct mount *mp;
94 vnode_t devvp;
95 user_addr_t data;
96 vfs_context_t context;
97 {
98 int error = 0;
99 struct user_null_args args;
100 struct vnode *lowerrootvp, *vp;
101 struct vnode *nullm_rootvp;
102 struct null_mount *xmp;
103 u_int size;
104
105 #ifdef NULLFS_DIAGNOSTIC
106 printf("nullfs_mount(mp = %x)\n", mp);
107 #endif
108
109 /*
110 * Update is a no-op
111 */
112 if (mp->mnt_flag & MNT_UPDATE) {
113 return (ENOTSUP);
114 /* return VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, devvp, data, p);*/
115 }
116
117 /*
118 * Get argument
119 */
120 if (vfs_context_is64bit(context)) {
121 error = copyin(data, (caddr_t)&args, sizeof (args));
122 }
123 else {
124 struct null_args temp;
125 error = copyin(data, (caddr_t)&temp, sizeof (temp));
126 args.target = CAST_USER_ADDR_T(temp.target);
127 }
128 if (error)
129 return (error);
130
131 /*
132 * Find lower node
133 */
134 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
135 UIO_USERSPACE, args.target, context);
136 if (error = namei(ndp))
137 return (error);
138 nameidone(ndp);
139 /*
140 * Sanity check on lower vnode
141 */
142 lowerrootvp = ndp->ni_vp;
143
144 vnode_put(ndp->ni_dvp);
145 ndp->ni_dvp = NULL;
146
147 xmp = (struct null_mount *) _MALLOC(sizeof(struct null_mount),
148 M_UFSMNT, M_WAITOK); /* XXX */
149
150 /*
151 * Save reference to underlying FS
152 */
153 xmp->nullm_vfs = lowerrootvp->v_mount;
154
155 /*
156 * Save reference. Each mount also holds
157 * a reference on the root vnode.
158 */
159 error = null_node_create(mp, lowerrootvp, &vp);
160 /*
161 * Make sure the node alias worked
162 */
163 if (error) {
164 vnode_put(lowerrootvp);
165 FREE(xmp, M_UFSMNT); /* XXX */
166 return (error);
167 }
168
169 /*
170 * Keep a held reference to the root vnode.
171 * It is vnode_put'd in nullfs_unmount.
172 */
173 nullm_rootvp = vp;
174 nullm_rootvp->v_flag |= VROOT;
175 xmp->nullm_rootvp = nullm_rootvp;
176 if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
177 mp->mnt_flag |= MNT_LOCAL;
178 mp->mnt_data = (qaddr_t) xmp;
179 vfs_getnewfsid(mp);
180
181 (void) copyinstr(args.target, mp->mnt_vfsstat.f_mntfromname, MAXPATHLEN - 1,
182 &size);
183 bzero(mp->mnt_vfsstat.f_mntfromname + size, MNAMELEN - size);
184 #ifdef NULLFS_DIAGNOSTIC
185 printf("nullfs_mount: lower %s, alias at %s\n",
186 mp->mnt_vfsstat.f_mntfromname, mp->mnt_vfsstat.f_mntonname);
187 #endif
188 return (0);
189 }
190
191 /*
192 * VFS start. Nothing needed here - the start routine
193 * on the underlying filesystem will have been called
194 * when that filesystem was mounted.
195 */
196 static int
197 nullfs_start(mp, flags, context)
198 struct mount *mp;
199 int flags;
200 vfs_context_t context;
201 {
202 return (0);
203 /* return VFS_START(MOUNTTONULLMOUNT(mp)->nullm_vfs, flags, context); */
204 }
205
206 /*
207 * Free reference to null layer
208 */
209 static int
210 nullfs_unmount(mp, mntflags, context)
211 struct mount *mp;
212 int mntflags;
213 vfs_context_t context;
214 {
215 struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
216 int error;
217 int flags = 0;
218 int force = 0;
219
220 #ifdef NULLFS_DIAGNOSTIC
221 printf("nullfs_unmount(mp = %x)\n", mp);
222 #endif
223
224 if (mntflags & MNT_FORCE) {
225 flags |= FORCECLOSE;
226 force = 1;
227 }
228
229 if ( (nullm_rootvp->v_usecount > 1) && !force )
230 return (EBUSY);
231 if ( (error = vflush(mp, nullm_rootvp, flags)) && !force )
232 return (error);
233
234 #ifdef NULLFS_DIAGNOSTIC
235 vprint("alias root of lower", nullm_rootvp);
236 #endif
237 /*
238 * Release reference on underlying root vnode
239 */
240 vnode_put(nullm_rootvp);
241 /*
242 * And blow it away for future re-use
243 */
244 vnode_reclaim(nullm_rootvp);
245 /*
246 * Finally, throw away the null_mount structure
247 */
248 FREE(mp->mnt_data, M_UFSMNT); /* XXX */
249 mp->mnt_data = 0;
250 return 0;
251 }
252
253 static int
254 nullfs_root(mp, vpp, context)
255 struct mount *mp;
256 struct vnode **vpp;
257 vfs_context_t context;
258 {
259 struct proc *p = curproc; /* XXX */
260 struct vnode *vp;
261
262 #ifdef NULLFS_DIAGNOSTIC
263 printf("nullfs_root(mp = %x, vp = %x->%x)\n", mp,
264 MOUNTTONULLMOUNT(mp)->nullm_rootvp,
265 NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp)
266 );
267 #endif
268
269 /*
270 * Return locked reference to root.
271 */
272 vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
273 vnode_get(vp);
274 *vpp = vp;
275 return 0;
276 }
277
278 static int
279 nullfs_quotactl(mp, cmd, uid, datap, context)
280 struct mount *mp;
281 int cmd;
282 uid_t uid;
283 caddr_t datap;
284 vfs_context_t context;
285 {
286 return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, datap, context);
287 }
288
289 static int
290 nullfs_statfs(mp, sbp, context)
291 struct mount *mp;
292 struct vfsstatfs *sbp;
293 vfs_context_t context;
294 {
295 int error;
296 struct vfsstatfs mstat;
297
298 #ifdef NULLFS_DIAGNOSTIC
299 printf("nullfs_statfs(mp = %x, vp = %x->%x)\n", mp,
300 MOUNTTONULLMOUNT(mp)->nullm_rootvp,
301 NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp)
302 );
303 #endif
304
305 bzero(&mstat, sizeof(mstat));
306
307 error = VFS_STATFS(MOUNTTONULLMOUNT(mp)->nullm_vfs, &mstat, context);
308 if (error)
309 return (error);
310
311 /* now copy across the "interesting" information and fake the rest */
312 //sbp->f_type = mstat.f_type;
313 sbp->f_flags = mstat.f_flags;
314 sbp->f_bsize = mstat.f_bsize;
315 sbp->f_iosize = mstat.f_iosize;
316 sbp->f_blocks = mstat.f_blocks;
317 sbp->f_bfree = mstat.f_bfree;
318 sbp->f_bavail = mstat.f_bavail;
319 sbp->f_files = mstat.f_files;
320 sbp->f_ffree = mstat.f_ffree;
321 return (0);
322 }
323
324 static int
325 nullfs_sync(__unused struct mount *mp, __unused int waitfor,
326 __unused kauth_cred_t cred, __unused vfs_context_t context)
327 {
328 /*
329 * XXX - Assumes no data cached at null layer.
330 */
331 return (0);
332 }
333
334 static int
335 nullfs_vget(mp, ino, vpp, context)
336 struct mount *mp;
337 ino64_t ino;
338 struct vnode **vpp;
339 vfs_context_t context;
340 {
341
342 return VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, vpp, context);
343 }
344
345 static int
346 nullfs_fhtovp(mp, fhlen, fhp, vpp, context)
347 struct mount *mp;
348 int fhlen;
349 unsigned char *fhp;
350 struct vnode **vpp;
351 vfs_context_t context;
352 {
353
354 return VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fhlen, fhp, vpp, context);
355 }
356
357 static int
358 nullfs_vptofh(vp, fhlenp, fhp, context)
359 struct vnode *vp;
360 int *fhlenp;
361 unsigned char *fhp;
362 vfs_context_t context;
363 {
364 return VFS_VPTOFH(NULLVPTOLOWERVP(vp), fhlenp, fhp, context);
365 }
366
367 int nullfs_init (struct vfsconf *);
368
369 #define nullfs_sysctl (int (*) (int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, proc_t))eopnotsupp
370
371 struct vfsops null_vfsops = {
372 nullfs_mount,
373 nullfs_start,
374 nullfs_unmount,
375 nullfs_root,
376 nullfs_quotactl,
377 nullfs_statfs,
378 nullfs_sync,
379 nullfs_vget,
380 nullfs_fhtovp,
381 nullfs_vptofh,
382 nullfs_init,
383 nullfs_sysctl
384 };