]> git.saurik.com Git - apple/xnu.git/blame - bsd/vfs/vfs_init.c
xnu-344.49.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_init.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26/*
27 * Copyright (c) 1989, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * This code is derived from software contributed
31 * to Berkeley by John Heidemann of the UCLA Ficus project.
32 *
33 * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * @(#)vfs_init.c 8.5 (Berkeley) 5/11/95
64 */
65
66
67#include <sys/param.h>
68#include <sys/mount.h>
69#include <sys/time.h>
70#include <sys/vm.h>
71#include <sys/vnode.h>
72#include <sys/stat.h>
73#include <sys/namei.h>
74#include <sys/ucred.h>
75#include <sys/buf.h>
76#include <sys/errno.h>
77#include <sys/malloc.h>
78
79
80/*
81 * Sigh, such primitive tools are these...
82 */
83#if 0
84#define DODEBUG(A) A
85#else
86#define DODEBUG(A)
87#endif
88
89extern uid_t console_user;
90extern struct vnodeopv_desc *vfs_opv_descs[];
91 /* a list of lists of vnodeops defns */
92extern struct vnodeop_desc *vfs_op_descs[];
93 /* and the operations they perform */
94/*
95 * This code doesn't work if the defn is **vnodop_defns with cc.
96 * The problem is because of the compiler sometimes putting in an
97 * extra level of indirection for arrays. It's an interesting
98 * "feature" of C.
99 */
100int vfs_opv_numops;
101
102typedef (*PFI)(); /* the standard Pointer to a Function returning an Int */
103
104/*
105 * A miscellaneous routine.
106 * A generic "default" routine that just returns an error.
107 */
108int
109vn_default_error()
110{
111
112 return (EOPNOTSUPP);
113}
114
115/*
116 * vfs_init.c
117 *
118 * Allocate and fill in operations vectors.
119 *
120 * An undocumented feature of this approach to defining operations is that
121 * there can be multiple entries in vfs_opv_descs for the same operations
122 * vector. This allows third parties to extend the set of operations
123 * supported by another layer in a binary compatibile way. For example,
124 * assume that NFS needed to be modified to support Ficus. NFS has an entry
125 * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by
126 * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions)
127 * listing those new operations Ficus adds to NFS, all without modifying the
128 * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but
129 * that is a(whole)nother story.) This is a feature.
130 */
131void
132vfs_opv_init()
133{
134 int i, j, k;
135 int (***opv_desc_vector_p)(void *);
136 int (**opv_desc_vector)(void *);
137 struct vnodeopv_entry_desc *opve_descp;
138
139 /*
140 * Allocate the dynamic vectors and fill them in.
141 */
142 for (i=0; vfs_opv_descs[i]; i++) {
143 opv_desc_vector_p = vfs_opv_descs[i]->opv_desc_vector_p;
144 /*
145 * Allocate and init the vector, if it needs it.
146 * Also handle backwards compatibility.
147 */
148 if (*opv_desc_vector_p == NULL) {
149 /* XXX - shouldn't be M_VNODE */
150 MALLOC(*opv_desc_vector_p, PFI*,
151 vfs_opv_numops*sizeof(PFI), M_VNODE, M_WAITOK);
152 bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI));
153 DODEBUG(printf("vector at %x allocated\n",
154 opv_desc_vector_p));
155 }
156 opv_desc_vector = *opv_desc_vector_p;
157 for (j=0; vfs_opv_descs[i]->opv_desc_ops[j].opve_op; j++) {
158 opve_descp = &(vfs_opv_descs[i]->opv_desc_ops[j]);
159
160 /*
161 * Sanity check: is this operation listed
162 * in the list of operations? We check this
163 * by seeing if its offest is zero. Since
164 * the default routine should always be listed
165 * first, it should be the only one with a zero
166 * offset. Any other operation with a zero
167 * offset is probably not listed in
168 * vfs_op_descs, and so is probably an error.
169 *
170 * A panic here means the layer programmer
171 * has committed the all-too common bug
172 * of adding a new operation to the layer's
173 * list of vnode operations but
174 * not adding the operation to the system-wide
175 * list of supported operations.
176 */
177 if (opve_descp->opve_op->vdesc_offset == 0 &&
178 opve_descp->opve_op->vdesc_offset !=
179 VOFFSET(vop_default)) {
180 printf("operation %s not listed in %s.\n",
181 opve_descp->opve_op->vdesc_name,
182 "vfs_op_descs");
183 panic ("vfs_opv_init: bad operation");
184 }
185 /*
186 * Fill in this entry.
187 */
188 opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
189 opve_descp->opve_impl;
190 }
191 }
192 /*
193 * Finally, go back and replace unfilled routines
194 * with their default. (Sigh, an O(n^3) algorithm. I
195 * could make it better, but that'd be work, and n is small.)
196 */
197 for (i = 0; vfs_opv_descs[i]; i++) {
198 opv_desc_vector = *(vfs_opv_descs[i]->opv_desc_vector_p);
199 /*
200 * Force every operations vector to have a default routine.
201 */
202 if (opv_desc_vector[VOFFSET(vop_default)]==NULL) {
203 panic("vfs_opv_init: operation vector without default routine.");
204 }
205 for (k = 0; k<vfs_opv_numops; k++)
206 if (opv_desc_vector[k] == NULL)
207 opv_desc_vector[k] =
208 opv_desc_vector[VOFFSET(vop_default)];
209 }
210}
211
212/*
213 * Initialize known vnode operations vectors.
214 */
215void
216vfs_op_init()
217{
218 int i;
219
220 DODEBUG(printf("Vnode_interface_init.\n"));
221 /*
222 * Set all vnode vectors to a well known value.
223 */
224 for (i = 0; vfs_opv_descs[i]; i++)
225 *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL;
226 /*
227 * Figure out how many ops there are by counting the table,
228 * and assign each its offset.
229 */
230 for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) {
231 vfs_op_descs[i]->vdesc_offset = vfs_opv_numops;
232 vfs_opv_numops++;
233 }
234 DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops));
235}
236
237/*
238 * Routines having to do with the management of the vnode table.
239 */
240extern struct vnodeops dead_vnodeops;
241extern struct vnodeops spec_vnodeops;
242struct vattr va_null;
243
244/*
245 * Initialize the vnode structures and initialize each file system type.
246 */
247vfsinit()
248{
249 struct vfsconf *vfsp;
250 int i, maxtypenum;
251
252 /*
253 * Initialize the "console user" for access purposes:
254 */
255 console_user = (uid_t)0;
256
257 /*
258 * Initialize the vnode table
259 */
260 vntblinit();
261 /*
262 * Initialize the vnode name cache
263 */
264 nchinit();
265 /*
266 * Build vnode operation vectors.
267 */
268 vfs_op_init();
269 vfs_opv_init(); /* finish the job */
270 /*
271 * Initialize each file system type.
272 */
273 vattr_null(&va_null);
274 numused_vfsslots = maxtypenum = 0;
275 for (vfsp = vfsconf, i = 0; i < maxvfsconf; i++, vfsp++) {
276 if (vfsp->vfc_vfsops == (struct vfsops *)0)
277 break;
278 if (i) vfsconf[i-1].vfc_next = vfsp;
279 if (maxtypenum <= vfsp->vfc_typenum)
280 maxtypenum = vfsp->vfc_typenum + 1;
281 (*vfsp->vfc_vfsops->vfs_init)(vfsp);
282 numused_vfsslots++;
283 }
284 /* next vfc_typenum to be used */
285 maxvfsconf = maxtypenum;
286}
287
288int
289vfsconf_add(struct vfsconf *nvfsp)
290{
291 struct vfsconf *vfsp;
292
293 if ((numused_vfsslots >= maxvfsslots) || (nvfsp == (struct vfsconf *)0))
294 return (-1);
295 bcopy(nvfsp, &vfsconf[numused_vfsslots], sizeof(struct vfsconf));
296 vfsconf[numused_vfsslots-1].vfc_next = &vfsconf[numused_vfsslots];
297
298 if (nvfsp->vfc_typenum <= maxvfsconf )
299 maxvfsconf = nvfsp->vfc_typenum + 1;
300 numused_vfsslots++;
301 if (nvfsp->vfc_vfsops->vfs_init)
302 (*nvfsp->vfc_vfsops->vfs_init)(nvfsp);
303 return(0);
304}
305
306int
307vfsconf_del(char * fs_name)
308{
309 int entriesRemaining;
310 struct vfsconf *vfsconflistentry;
311 struct vfsconf *prevconf = NULL;
312 struct vfsconf *targetconf = NULL;
313
314 prevconf = vfsconflistentry = vfsconf;
315 for (entriesRemaining = maxvfsslots;
316 (entriesRemaining > 0) && (vfsconflistentry != NULL);
317 --entriesRemaining) {
318 if ((vfsconflistentry->vfc_vfsops != NULL) && (strcmp(vfsconflistentry->vfc_name, fs_name) == 0)) {
319 targetconf = vfsconflistentry;
320 break;
321 };
322 prevconf = vfsconflistentry;
323 vfsconflistentry = vfsconflistentry->vfc_next;
324 };
325
326 if (targetconf != NULL) {
327 if (prevconf != NULL) {
328 /* Unlink the target entry from the list:
329 and decrement our count */
330 prevconf->vfc_next = targetconf->vfc_next;
331 numused_vfsslots--;
332 } else {
333 /* XXX need real error code for no previous entry in list */
334 return(-1);
335 }
336 } else {
337 /* XXX need real error code for entry not found */
338 return(-1);
339 };
340 return(0);
341}