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