1 /* $NetBSD: vfs_init.c,v 1.21 2002/03/08 20:48:42 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1989, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * This code is derived from software contributed 45 * to Berkeley by John Heidemann of the UCLA Ficus project. 46 * 47 * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 48 * 49 * Redistribution and use in source and binary forms, with or without 50 * modification, are permitted provided that the following conditions 51 * are met: 52 * 1. Redistributions of source code must retain the above copyright 53 * notice, this list of conditions and the following disclaimer. 54 * 2. Redistributions in binary form must reproduce the above copyright 55 * notice, this list of conditions and the following disclaimer in the 56 * documentation and/or other materials provided with the distribution. 57 * 3. All advertising materials mentioning features or use of this software 58 * must display the following acknowledgement: 59 * This product includes software developed by the University of 60 * California, Berkeley and its contributors. 61 * 4. Neither the name of the University nor the names of its contributors 62 * may be used to endorse or promote products derived from this software 63 * without specific prior written permission. 64 * 65 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 66 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 67 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 68 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 69 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 70 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 71 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 72 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 73 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 74 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 75 * SUCH DAMAGE. 76 * 77 * @(#)vfs_init.c 8.5 (Berkeley) 5/11/95 78 */ 79 80 #include <sys/cdefs.h> 81 __KERNEL_RCSID(0, "$NetBSD: vfs_init.c,v 1.21 2002/03/08 20:48:42 thorpej Exp $"); 82 83 #include <sys/param.h> 84 #include <sys/mount.h> 85 #include <sys/time.h> 86 #include <sys/vnode.h> 87 #include <sys/stat.h> 88 #include <sys/namei.h> 89 #include <sys/ucred.h> 90 #include <sys/buf.h> 91 #include <sys/errno.h> 92 #include <sys/malloc.h> 93 #include <sys/systm.h> 94 95 /* 96 * Sigh, such primitive tools are these... 97 */ 98 #if 0 99 #define DODEBUG(A) A 100 #else 101 #define DODEBUG(A) 102 #endif 103 104 /* 105 * The global list of vnode operations. 106 */ 107 extern const struct vnodeop_desc * const vfs_op_descs[]; 108 109 /* 110 * These vnodeopv_descs are listed here because they are not 111 * associated with any particular file system, and thus cannot 112 * be initialized by vfs_attach(). 113 */ 114 extern const struct vnodeopv_desc dead_vnodeop_opv_desc; 115 extern const struct vnodeopv_desc fifo_vnodeop_opv_desc; 116 extern const struct vnodeopv_desc spec_vnodeop_opv_desc; 117 extern const struct vnodeopv_desc sync_vnodeop_opv_desc; 118 119 const struct vnodeopv_desc * const vfs_special_vnodeopv_descs[] = { 120 &dead_vnodeop_opv_desc, 121 &fifo_vnodeop_opv_desc, 122 &spec_vnodeop_opv_desc, 123 &sync_vnodeop_opv_desc, 124 NULL, 125 }; 126 127 /* 128 * This code doesn't work if the defn is **vnodop_defns with cc. 129 * The problem is because of the compiler sometimes putting in an 130 * extra level of indirection for arrays. It's an interesting 131 * "feature" of C. 132 */ 133 typedef int (*PFI) __P((void *)); 134 135 static void vfs_opv_init_explicit __P((const struct vnodeopv_desc *)); 136 static void vfs_opv_init_default __P((const struct vnodeopv_desc *)); 137 #ifdef DEBUG 138 static void vfs_op_check __P((void)); 139 #endif 140 141 /* 142 * A miscellaneous routine. 143 * A generic "default" routine that just returns an error. 144 */ 145 /*ARGSUSED*/ 146 int 147 vn_default_error(v) 148 void *v; 149 { 150 151 return (EOPNOTSUPP); 152 } 153 154 /* 155 * vfs_init.c 156 * 157 * Allocate and fill in operations vectors. 158 * 159 * An undocumented feature of this approach to defining operations is that 160 * there can be multiple entries in vfs_opv_descs for the same operations 161 * vector. This allows third parties to extend the set of operations 162 * supported by another layer in a binary compatibile way. For example, 163 * assume that NFS needed to be modified to support Ficus. NFS has an entry 164 * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 165 * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 166 * listing those new operations Ficus adds to NFS, all without modifying the 167 * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 168 * that is a(whole)nother story.) This is a feature. 169 */ 170 171 /* 172 * Init the vector, if it needs it. 173 * Also handle backwards compatibility. 174 */ 175 static void 176 vfs_opv_init_explicit(vfs_opv_desc) 177 const struct vnodeopv_desc *vfs_opv_desc; 178 { 179 int (**opv_desc_vector) __P((void *)); 180 const struct vnodeopv_entry_desc *opve_descp; 181 182 opv_desc_vector = *(vfs_opv_desc->opv_desc_vector_p); 183 184 for (opve_descp = vfs_opv_desc->opv_desc_ops; 185 opve_descp->opve_op; 186 opve_descp++) { 187 /* 188 * Sanity check: is this operation listed 189 * in the list of operations? We check this 190 * by seeing if its offest is zero. Since 191 * the default routine should always be listed 192 * first, it should be the only one with a zero 193 * offset. Any other operation with a zero 194 * offset is probably not listed in 195 * vfs_op_descs, and so is probably an error. 196 * 197 * A panic here means the layer programmer 198 * has committed the all-too common bug 199 * of adding a new operation to the layer's 200 * list of vnode operations but 201 * not adding the operation to the system-wide 202 * list of supported operations. 203 */ 204 if (opve_descp->opve_op->vdesc_offset == 0 && 205 opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) { 206 printf("operation %s not listed in %s.\n", 207 opve_descp->opve_op->vdesc_name, "vfs_op_descs"); 208 panic ("vfs_opv_init: bad operation"); 209 } 210 211 /* 212 * Fill in this entry. 213 */ 214 opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 215 opve_descp->opve_impl; 216 } 217 } 218 219 static void 220 vfs_opv_init_default(vfs_opv_desc) 221 const struct vnodeopv_desc *vfs_opv_desc; 222 { 223 int j; 224 int (**opv_desc_vector) __P((void *)); 225 226 opv_desc_vector = *(vfs_opv_desc->opv_desc_vector_p); 227 228 /* 229 * Force every operations vector to have a default routine. 230 */ 231 if (opv_desc_vector[VOFFSET(vop_default)] == NULL) 232 panic("vfs_opv_init: operation vector without default routine."); 233 234 for (j = 0; j < VNODE_OPS_COUNT; j++) 235 if (opv_desc_vector[j] == NULL) 236 opv_desc_vector[j] = 237 opv_desc_vector[VOFFSET(vop_default)]; 238 } 239 240 void 241 vfs_opv_init(vopvdpp) 242 const struct vnodeopv_desc * const *vopvdpp; 243 { 244 int (**opv_desc_vector) __P((void *)); 245 int i; 246 247 /* 248 * Allocate the vectors. 249 */ 250 for (i = 0; vopvdpp[i] != NULL; i++) { 251 /* XXX - shouldn't be M_VNODE */ 252 opv_desc_vector = 253 malloc(VNODE_OPS_COUNT * sizeof(PFI), M_VNODE, M_WAITOK); 254 memset(opv_desc_vector, 0, VNODE_OPS_COUNT * sizeof(PFI)); 255 *(vopvdpp[i]->opv_desc_vector_p) = opv_desc_vector; 256 DODEBUG(printf("vector at %p allocated\n", 257 opv_desc_vector_p)); 258 } 259 260 /* 261 * ...and fill them in. 262 */ 263 for (i = 0; vopvdpp[i] != NULL; i++) 264 vfs_opv_init_explicit(vopvdpp[i]); 265 266 /* 267 * Finally, go back and replace unfilled routines 268 * with their default. 269 */ 270 for (i = 0; vopvdpp[i] != NULL; i++) 271 vfs_opv_init_default(vopvdpp[i]); 272 } 273 274 void 275 vfs_opv_free(vopvdpp) 276 const struct vnodeopv_desc * const *vopvdpp; 277 { 278 int i; 279 280 /* 281 * Free the vectors allocated in vfs_opv_init(). 282 */ 283 for (i = 0; vopvdpp[i] != NULL; i++) { 284 /* XXX - shouldn't be M_VNODE */ 285 free(*(vopvdpp[i]->opv_desc_vector_p), M_VNODE); 286 *(vopvdpp[i]->opv_desc_vector_p) = NULL; 287 } 288 } 289 290 #ifdef DEBUG 291 static void 292 vfs_op_check() 293 { 294 int i; 295 296 DODEBUG(printf("Vnode_interface_init.\n")); 297 298 /* 299 * Check offset of each op. 300 */ 301 for (i = 0; vfs_op_descs[i]; i++) { 302 if (vfs_op_descs[i]->vdesc_offset != i) 303 panic("vfs_op_check: vfs_op_desc[] offset mismatch"); 304 } 305 306 if (i != VNODE_OPS_COUNT) { 307 panic("vfs_op_check: vnode ops count mismatch (%d != %d)", 308 i, VNODE_OPS_COUNT); 309 } 310 311 DODEBUG(printf ("vfs_opv_numops=%d\n", VNODE_OPS_COUNT)); 312 } 313 #endif /* DEBUG */ 314 315 /* 316 * Routines having to do with the management of the vnode table. 317 */ 318 struct vattr va_null; 319 320 /* 321 * Initialize the vnode structures and initialize each file system type. 322 */ 323 void 324 vfsinit() 325 { 326 extern struct vfsops *vfs_list_initial[]; 327 int i; 328 329 /* 330 * Initialize the namei pathname buffer pool and cache. 331 */ 332 pool_init(&pnbuf_pool, MAXPATHLEN, 0, 0, 0, "pnbufpl", 333 &pool_allocator_nointr); 334 pool_cache_init(&pnbuf_cache, &pnbuf_pool, NULL, NULL, NULL); 335 336 /* 337 * Initialize the vnode table 338 */ 339 vntblinit(); 340 341 /* 342 * Initialize the vnode name cache 343 */ 344 nchinit(); 345 346 #ifdef DEBUG 347 /* 348 * Check the list of vnode operations. 349 */ 350 vfs_op_check(); 351 #endif 352 353 /* 354 * Initialize the special vnode operations. 355 */ 356 vfs_opv_init(vfs_special_vnodeopv_descs); 357 358 /* 359 * Establish each file system which was statically 360 * included in the kernel. 361 */ 362 vattr_null(&va_null); 363 for (i = 0; vfs_list_initial[i] != NULL; i++) { 364 if (vfs_attach(vfs_list_initial[i])) { 365 printf("multiple `%s' file systems", 366 vfs_list_initial[i]->vfs_name); 367 panic("vfsinit"); 368 } 369 } 370 } 371