xref: /csrg-svn/sys/kern/vfs_init.c (revision 54289)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed
6  * to Berkeley by John Heidemann of the UCLA Ficus project.
7  *
8  * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
9  *
10  * %sccs.include.redist.c%
11  *
12  *	@(#)vfs_init.c	7.1 (Berkeley) 06/23/92
13  */
14 
15 
16 #include <sys/param.h>
17 #include <sys/mount.h>
18 #include <sys/time.h>
19 #include <sys/vnode.h>
20 #include <sys/stat.h>
21 #include <sys/specdev.h>
22 #include <sys/namei.h>
23 #include <sys/ucred.h>
24 #include <sys/buf.h>
25 #include <sys/errno.h>
26 #include <sys/malloc.h>
27 
28 
29 /* Sigh, such primitive tools are these... */
30 #if 0
31 #define DODEBUG(A) A
32 #else
33 #define DODEBUG(A)
34 #endif
35 
36 
37 
38 extern struct vnodeopv_desc *vfs_opv_descs[];
39 				/* a list of lists of vnodeops defns */
40 extern struct vnodeop_desc *vfs_op_descs[];
41 				/* and the operations they perform */
42 /*
43  * This code doesn't work if the defn is **vnodop_defns with cc.
44  * The problem is because of the compiler sometimes putting in an
45  * extra level of indirection for arrays.  It's an interesting
46  * "feature" of C.
47  */
48 int vfs_opv_numops;
49 
50 typedef (*PFI)();   /* the standard Pointer to a Function returning an Int */
51 
52 
53 
54 /*
55  * A miscellaneous routine.
56  * A generic "default" routine that just returns an error.
57  */
58 int
59 vn_default_error()
60 {
61 	return EOPNOTSUPP;
62 }
63 
64 
65 
66 
67 /*
68  * vfs_init.c
69  *
70  * Allocate and fill in operations vectors.
71  *
72  * An undocumented feature of this approach to defining
73  * operations is that there can be multiple entries in
74  * vfs_opv_descs for the same operations vector.
75  * This allows third parties to extend the set of operations
76  * supported by another layer in a binary compatibile way.
77  * For example, assume that NFS needed to be modified to support
78  * Ficus.  NFS has an entry (probably nfs_vnopdeop_decls)
79  * declaring all the operations NFS supports by default.
80  * Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions)
81  * listing those new operations Ficus adds to NFS, all without
82  * modifying the NFS code.  (Of couse, the OTW NFS protocol
83  * still needs to be munged, but that's a(whole)nother story.)
84  * This is a feature.
85  */
86 
87 void
88 vfs_opv_init()
89 {
90 	int i, j, k;
91 	struct vnodeop_defn *defnp;
92 	int (***opv_desc_vector_p)();
93 	int (**opv_desc_vector)();
94 	struct vnodeopv_entry_desc *opve_descp;
95 
96 	/*
97 	 * Allocate the dynamic vectors and fill them in.
98 	 */
99 	for (i=0; vfs_opv_descs[i]; i++) {
100 		opv_desc_vector_p = vfs_opv_descs[i]->opv_desc_vector_p;
101 		/*
102 		 * Allocate and init the vector, if it needs it.
103 		 * Also handle backwards compatibility.
104 		 */
105 		if (*opv_desc_vector_p == NULL) {
106 			/* XXX - shouldn't be M_VNODE */
107 			MALLOC(*opv_desc_vector_p, PFI*,
108 			       vfs_opv_numops*sizeof(PFI), M_VNODE, M_WAITOK);
109 			bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI));
110 			DODEBUG(printf("vector at %x allocated\n", opv_desc_vector_p));
111 		};
112 		opv_desc_vector = *opv_desc_vector_p;
113 		for (j=0; vfs_opv_descs[i]->opv_desc_ops[j].opve_op; j++) {
114 			opve_descp = &(vfs_opv_descs[i]->opv_desc_ops[j]);
115 
116 			/*
117 			 * Sanity check:  is this operation listed
118 			 * in the list of operations?  We check this
119 			 * by seeing if its offest is zero.  Since
120 			 * the default routine should always be listed
121 			 * first, it should be the only one with a zero
122 			 * offset.  Any other operation with a zero
123 			 * offset is probably not listed in
124 			 * vfs_op_descs,
125 			 * and so is probably an error.
126 			 *
127 			 * A panic here means the layer programmer
128 			 * has committed the all-too common bug
129 			 * of adding a new operation to the layer's
130 			 * list of vnode operations but
131 			 * not adding the operation to the system-wide
132 			 * list of supported operations.
133 			 */
134 			if (opve_descp->opve_op->vdesc_offset == 0 &&
135 				    opve_descp->opve_op->vdesc_offset !=
136 				    	VOFFSET(vop_default)) {
137 				printf ("error: operation %s not listed in vfs_op_descs.\n", opve_descp->opve_op->vdesc_name);
138 				panic ("vfs_opv_init: bad operation");
139 			};
140 			/*
141 			 * Fill in this entry.
142 			 */
143 			opv_desc_vector[opve_descp->opve_op->vdesc_offset]=
144 					opve_descp->opve_impl;
145 		};
146 	};
147 
148 	/*
149 	 * Finally, go back and replace unfilled routines
150 	 * with their default.  (Sigh, an O(n^3) algorithm.  I
151 	 * could make it better, but that'd be work, and n is small.)
152 	 */
153 	for (i=0; vfs_opv_descs[i]; i++) {
154 		opv_desc_vector = *(vfs_opv_descs[i]->opv_desc_vector_p);
155 		/*
156 		 * Force every operations vector to have a default routine.
157 		 */
158 		if (opv_desc_vector[VOFFSET(vop_default)]==NULL) {
159 			panic("vfs_opv_init: operation vector without default routine.");
160 		};
161 		for (k=0; k<vfs_opv_numops; k++)
162 			if (opv_desc_vector[k] == NULL)
163 				opv_desc_vector[k] =
164 					opv_desc_vector[VOFFSET(vop_default)];
165 	};
166 }
167 
168 
169 
170 
171 void
172 vfs_op_init()
173 {
174 	int i, j;
175 
176 	DODEBUG(printf ("Vnode_interface_init.\n"));
177 
178 	/*
179 	 * Set all vnode vectors to a well known value.
180 	 */
181 	for (i=0; vfs_opv_descs[i]; i++)
182 		*(vfs_opv_descs[i]->opv_desc_vector_p) = NULL;
183 
184 	vfs_opv_numops = 0;
185 
186 	/*
187 	 * Figure out how many ops there are by counting the table,
188 	 * and assign each its offset.
189 	 */
190 	for (i=0; vfs_op_descs[i]; i++) {
191 		vfs_op_descs[i]->vdesc_offset = vfs_opv_numops;
192 		vfs_opv_numops++;
193 	};
194 
195 	DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops));
196 }
197 
198 
199 
200 
201 
202 
203 
204 /*
205  * Routines having to do with the management of the vnode table.
206  */
207 struct vnode *vfreeh, **vfreet;
208 extern struct vnodeops dead_vnodeops;
209 extern struct vnodeops spec_vnodeops;
210 extern void vclean();
211 struct vattr va_null;
212 
213 /*
214  * Initialize the vnode structures and initialize each file system type.
215  */
216 vfsinit()
217 {
218 	struct vfsops **vfsp;
219 
220 	/*
221 	 * Initialize the vnode name cache
222 	 */
223 	nchinit();
224 	/*
225 	 * Build vnode operation vectors.
226 	 */
227 	vfs_op_init();
228 	vfs_opv_init();   /* finish the job */
229 	/*
230 	 * Initialize each file system type.
231 	 */
232 	vattr_null(&va_null);
233 	for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) {
234 		if (*vfsp == NULL)
235 			continue;
236 		(*(*vfsp)->vfs_init)();
237 	}
238 }
239