]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
5d5c5d0d A |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. |
3 | * | |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
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. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
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. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
27 | */ |
28 | /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ | |
29 | /* | |
30 | * Copyright (c) 1992, 1993 | |
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 | * @(#)null_vfsops.c 8.7 (Berkeley) 5/14/95 | |
65 | * | |
66 | * @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92 | |
67 | */ | |
68 | ||
69 | /* | |
70 | * Null Layer | |
71 | * (See null_vnops.c for a description of what this does.) | |
72 | */ | |
73 | ||
74 | #include <sys/param.h> | |
75 | #include <sys/systm.h> | |
76 | #include <sys/proc.h> | |
91447636 | 77 | #include <sys/kauth.h> |
1c79356b A |
78 | #include <sys/time.h> |
79 | #include <sys/types.h> | |
80 | #include <sys/vnode.h> | |
91447636 | 81 | #include <sys/mount_internal.h> |
1c79356b A |
82 | #include <sys/namei.h> |
83 | #include <sys/malloc.h> | |
84 | #include <miscfs/nullfs/null.h> | |
85 | ||
86 | /* | |
87 | * Mount null layer | |
88 | */ | |
91447636 A |
89 | static int |
90 | nullfs_mount(mp, devvp, data, context) | |
1c79356b | 91 | struct mount *mp; |
91447636 A |
92 | vnode_t devvp; |
93 | user_addr_t data; | |
94 | vfs_context_t context; | |
1c79356b A |
95 | { |
96 | int error = 0; | |
91447636 | 97 | struct user_null_args args; |
1c79356b A |
98 | struct vnode *lowerrootvp, *vp; |
99 | struct vnode *nullm_rootvp; | |
100 | struct null_mount *xmp; | |
101 | u_int size; | |
102 | ||
103 | #ifdef NULLFS_DIAGNOSTIC | |
104 | printf("nullfs_mount(mp = %x)\n", mp); | |
105 | #endif | |
106 | ||
107 | /* | |
108 | * Update is a no-op | |
109 | */ | |
110 | if (mp->mnt_flag & MNT_UPDATE) { | |
91447636 A |
111 | return (ENOTSUP); |
112 | /* return VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, devvp, data, p);*/ | |
1c79356b A |
113 | } |
114 | ||
115 | /* | |
116 | * Get argument | |
117 | */ | |
91447636 A |
118 | if (vfs_context_is64bit(context)) { |
119 | error = copyin(data, (caddr_t)&args, sizeof (args)); | |
120 | } | |
121 | else { | |
122 | struct null_args temp; | |
123 | error = copyin(data, (caddr_t)&temp, sizeof (temp)); | |
124 | args.target = CAST_USER_ADDR_T(temp.target); | |
125 | } | |
126 | if (error) | |
1c79356b A |
127 | return (error); |
128 | ||
129 | /* | |
130 | * Find lower node | |
131 | */ | |
132 | NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, | |
91447636 | 133 | UIO_USERSPACE, args.target, context); |
1c79356b A |
134 | if (error = namei(ndp)) |
135 | return (error); | |
91447636 | 136 | nameidone(ndp); |
1c79356b A |
137 | /* |
138 | * Sanity check on lower vnode | |
139 | */ | |
140 | lowerrootvp = ndp->ni_vp; | |
141 | ||
91447636 | 142 | vnode_put(ndp->ni_dvp); |
1c79356b A |
143 | ndp->ni_dvp = NULL; |
144 | ||
145 | xmp = (struct null_mount *) _MALLOC(sizeof(struct null_mount), | |
146 | M_UFSMNT, M_WAITOK); /* XXX */ | |
147 | ||
148 | /* | |
149 | * Save reference to underlying FS | |
150 | */ | |
151 | xmp->nullm_vfs = lowerrootvp->v_mount; | |
152 | ||
153 | /* | |
154 | * Save reference. Each mount also holds | |
155 | * a reference on the root vnode. | |
156 | */ | |
157 | error = null_node_create(mp, lowerrootvp, &vp); | |
1c79356b A |
158 | /* |
159 | * Make sure the node alias worked | |
160 | */ | |
161 | if (error) { | |
91447636 | 162 | vnode_put(lowerrootvp); |
1c79356b A |
163 | FREE(xmp, M_UFSMNT); /* XXX */ |
164 | return (error); | |
165 | } | |
166 | ||
167 | /* | |
168 | * Keep a held reference to the root vnode. | |
91447636 | 169 | * It is vnode_put'd in nullfs_unmount. |
1c79356b A |
170 | */ |
171 | nullm_rootvp = vp; | |
172 | nullm_rootvp->v_flag |= VROOT; | |
173 | xmp->nullm_rootvp = nullm_rootvp; | |
174 | if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) | |
175 | mp->mnt_flag |= MNT_LOCAL; | |
176 | mp->mnt_data = (qaddr_t) xmp; | |
177 | vfs_getnewfsid(mp); | |
178 | ||
91447636 | 179 | (void) copyinstr(args.target, mp->mnt_vfsstat.f_mntfromname, MAXPATHLEN - 1, |
1c79356b | 180 | &size); |
91447636 | 181 | bzero(mp->mnt_vfsstat.f_mntfromname + size, MNAMELEN - size); |
1c79356b A |
182 | #ifdef NULLFS_DIAGNOSTIC |
183 | printf("nullfs_mount: lower %s, alias at %s\n", | |
91447636 | 184 | mp->mnt_vfsstat.f_mntfromname, mp->mnt_vfsstat.f_mntonname); |
1c79356b A |
185 | #endif |
186 | return (0); | |
187 | } | |
188 | ||
189 | /* | |
190 | * VFS start. Nothing needed here - the start routine | |
191 | * on the underlying filesystem will have been called | |
192 | * when that filesystem was mounted. | |
193 | */ | |
91447636 A |
194 | static int |
195 | nullfs_start(mp, flags, context) | |
1c79356b A |
196 | struct mount *mp; |
197 | int flags; | |
91447636 | 198 | vfs_context_t context; |
1c79356b A |
199 | { |
200 | return (0); | |
91447636 | 201 | /* return VFS_START(MOUNTTONULLMOUNT(mp)->nullm_vfs, flags, context); */ |
1c79356b A |
202 | } |
203 | ||
204 | /* | |
205 | * Free reference to null layer | |
206 | */ | |
91447636 A |
207 | static int |
208 | nullfs_unmount(mp, mntflags, context) | |
1c79356b A |
209 | struct mount *mp; |
210 | int mntflags; | |
91447636 | 211 | vfs_context_t context; |
1c79356b A |
212 | { |
213 | struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp; | |
214 | int error; | |
215 | int flags = 0; | |
9bccf70c | 216 | int force = 0; |
1c79356b A |
217 | |
218 | #ifdef NULLFS_DIAGNOSTIC | |
219 | printf("nullfs_unmount(mp = %x)\n", mp); | |
220 | #endif | |
221 | ||
9bccf70c | 222 | if (mntflags & MNT_FORCE) { |
1c79356b | 223 | flags |= FORCECLOSE; |
9bccf70c A |
224 | force = 1; |
225 | } | |
1c79356b | 226 | |
9bccf70c | 227 | if ( (nullm_rootvp->v_usecount > 1) && !force ) |
1c79356b | 228 | return (EBUSY); |
9bccf70c | 229 | if ( (error = vflush(mp, nullm_rootvp, flags)) && !force ) |
1c79356b A |
230 | return (error); |
231 | ||
232 | #ifdef NULLFS_DIAGNOSTIC | |
233 | vprint("alias root of lower", nullm_rootvp); | |
234 | #endif | |
235 | /* | |
236 | * Release reference on underlying root vnode | |
237 | */ | |
91447636 | 238 | vnode_put(nullm_rootvp); |
1c79356b A |
239 | /* |
240 | * And blow it away for future re-use | |
241 | */ | |
91447636 | 242 | vnode_reclaim(nullm_rootvp); |
1c79356b A |
243 | /* |
244 | * Finally, throw away the null_mount structure | |
245 | */ | |
246 | FREE(mp->mnt_data, M_UFSMNT); /* XXX */ | |
247 | mp->mnt_data = 0; | |
248 | return 0; | |
249 | } | |
250 | ||
91447636 A |
251 | static int |
252 | nullfs_root(mp, vpp, context) | |
1c79356b A |
253 | struct mount *mp; |
254 | struct vnode **vpp; | |
91447636 | 255 | vfs_context_t context; |
1c79356b A |
256 | { |
257 | struct proc *p = curproc; /* XXX */ | |
258 | struct vnode *vp; | |
259 | ||
260 | #ifdef NULLFS_DIAGNOSTIC | |
261 | printf("nullfs_root(mp = %x, vp = %x->%x)\n", mp, | |
262 | MOUNTTONULLMOUNT(mp)->nullm_rootvp, | |
263 | NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp) | |
264 | ); | |
265 | #endif | |
266 | ||
267 | /* | |
268 | * Return locked reference to root. | |
269 | */ | |
270 | vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp; | |
91447636 | 271 | vnode_get(vp); |
1c79356b A |
272 | *vpp = vp; |
273 | return 0; | |
274 | } | |
275 | ||
91447636 A |
276 | static int |
277 | nullfs_quotactl(mp, cmd, uid, datap, context) | |
1c79356b A |
278 | struct mount *mp; |
279 | int cmd; | |
280 | uid_t uid; | |
91447636 A |
281 | caddr_t datap; |
282 | vfs_context_t context; | |
1c79356b | 283 | { |
91447636 | 284 | return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, datap, context); |
1c79356b A |
285 | } |
286 | ||
91447636 A |
287 | static int |
288 | nullfs_statfs(mp, sbp, context) | |
1c79356b | 289 | struct mount *mp; |
91447636 A |
290 | struct vfsstatfs *sbp; |
291 | vfs_context_t context; | |
1c79356b A |
292 | { |
293 | int error; | |
91447636 | 294 | struct vfsstatfs mstat; |
1c79356b A |
295 | |
296 | #ifdef NULLFS_DIAGNOSTIC | |
297 | printf("nullfs_statfs(mp = %x, vp = %x->%x)\n", mp, | |
298 | MOUNTTONULLMOUNT(mp)->nullm_rootvp, | |
299 | NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp) | |
300 | ); | |
301 | #endif | |
302 | ||
303 | bzero(&mstat, sizeof(mstat)); | |
304 | ||
91447636 | 305 | error = VFS_STATFS(MOUNTTONULLMOUNT(mp)->nullm_vfs, &mstat, context); |
1c79356b A |
306 | if (error) |
307 | return (error); | |
308 | ||
309 | /* now copy across the "interesting" information and fake the rest */ | |
91447636 | 310 | //sbp->f_type = mstat.f_type; |
1c79356b A |
311 | sbp->f_flags = mstat.f_flags; |
312 | sbp->f_bsize = mstat.f_bsize; | |
313 | sbp->f_iosize = mstat.f_iosize; | |
314 | sbp->f_blocks = mstat.f_blocks; | |
315 | sbp->f_bfree = mstat.f_bfree; | |
316 | sbp->f_bavail = mstat.f_bavail; | |
317 | sbp->f_files = mstat.f_files; | |
318 | sbp->f_ffree = mstat.f_ffree; | |
1c79356b A |
319 | return (0); |
320 | } | |
321 | ||
91447636 A |
322 | static int |
323 | nullfs_sync(__unused struct mount *mp, __unused int waitfor, | |
324 | __unused kauth_cred_t cred, __unused vfs_context_t context) | |
1c79356b A |
325 | { |
326 | /* | |
327 | * XXX - Assumes no data cached at null layer. | |
328 | */ | |
329 | return (0); | |
330 | } | |
331 | ||
91447636 A |
332 | static int |
333 | nullfs_vget(mp, ino, vpp, context) | |
1c79356b | 334 | struct mount *mp; |
91447636 | 335 | ino64_t ino; |
1c79356b | 336 | struct vnode **vpp; |
91447636 | 337 | vfs_context_t context; |
1c79356b A |
338 | { |
339 | ||
91447636 | 340 | return VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, vpp, context); |
1c79356b A |
341 | } |
342 | ||
91447636 A |
343 | static int |
344 | nullfs_fhtovp(mp, fhlen, fhp, vpp, context) | |
1c79356b | 345 | struct mount *mp; |
91447636 A |
346 | int fhlen; |
347 | unsigned char *fhp; | |
1c79356b | 348 | struct vnode **vpp; |
91447636 | 349 | vfs_context_t context; |
1c79356b A |
350 | { |
351 | ||
91447636 | 352 | return VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fhlen, fhp, vpp, context); |
1c79356b A |
353 | } |
354 | ||
91447636 A |
355 | static int |
356 | nullfs_vptofh(vp, fhlenp, fhp, context) | |
1c79356b | 357 | struct vnode *vp; |
91447636 A |
358 | int *fhlenp; |
359 | unsigned char *fhp; | |
360 | vfs_context_t context; | |
1c79356b | 361 | { |
91447636 | 362 | return VFS_VPTOFH(NULLVPTOLOWERVP(vp), fhlenp, fhp, context); |
1c79356b A |
363 | } |
364 | ||
91447636 | 365 | int nullfs_init (struct vfsconf *); |
1c79356b | 366 | |
91447636 | 367 | #define nullfs_sysctl (int (*) (int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, proc_t))eopnotsupp |
1c79356b A |
368 | |
369 | struct vfsops null_vfsops = { | |
370 | nullfs_mount, | |
371 | nullfs_start, | |
372 | nullfs_unmount, | |
373 | nullfs_root, | |
374 | nullfs_quotactl, | |
375 | nullfs_statfs, | |
376 | nullfs_sync, | |
377 | nullfs_vget, | |
378 | nullfs_fhtovp, | |
379 | nullfs_vptofh, | |
380 | nullfs_init, | |
91447636 | 381 | nullfs_sysctl |
1c79356b | 382 | }; |