1 /* $NetBSD: vfs_init.c,v 1.8 1996/10/13 02:32:50 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed 8 * to Berkeley by John Heidemann of the UCLA Ficus project. 9 * 10 * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)vfs_init.c 8.3 (Berkeley) 1/4/94 41 */ 42 43 44 #include <sys/param.h> 45 #include <sys/mount.h> 46 #include <sys/time.h> 47 #include <sys/vnode.h> 48 #include <sys/stat.h> 49 #include <sys/namei.h> 50 #include <sys/ucred.h> 51 #include <sys/buf.h> 52 #include <sys/errno.h> 53 #include <sys/malloc.h> 54 #include <sys/systm.h> 55 56 /* 57 * Sigh, such primitive tools are these... 58 */ 59 #if 0 60 #define DODEBUG(A) A 61 #else 62 #define DODEBUG(A) 63 #endif 64 65 extern struct vnodeopv_desc *vfs_opv_descs[]; 66 /* a list of lists of vnodeops defns */ 67 extern struct vnodeop_desc *vfs_op_descs[]; 68 /* and the operations they perform */ 69 /* 70 * This code doesn't work if the defn is **vnodop_defns with cc. 71 * The problem is because of the compiler sometimes putting in an 72 * extra level of indirection for arrays. It's an interesting 73 * "feature" of C. 74 */ 75 int vfs_opv_numops; 76 77 typedef (*PFI) __P((void *)); 78 79 void vfs_opv_init __P((void)); 80 void vfs_opv_init_explicit __P((struct vnodeopv_desc *)); 81 void vfs_opv_init_default __P((struct vnodeopv_desc *)); 82 void vfs_op_init __P((void)); 83 84 /* 85 * A miscellaneous routine. 86 * A generic "default" routine that just returns an error. 87 */ 88 /*ARGSUSED*/ 89 int 90 vn_default_error(v) 91 void *v; 92 { 93 94 return (EOPNOTSUPP); 95 } 96 97 /* 98 * vfs_init.c 99 * 100 * Allocate and fill in operations vectors. 101 * 102 * An undocumented feature of this approach to defining operations is that 103 * there can be multiple entries in vfs_opv_descs for the same operations 104 * vector. This allows third parties to extend the set of operations 105 * supported by another layer in a binary compatibile way. For example, 106 * assume that NFS needed to be modified to support Ficus. NFS has an entry 107 * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 108 * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 109 * listing those new operations Ficus adds to NFS, all without modifying the 110 * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 111 * that is a(whole)nother story.) This is a feature. 112 */ 113 114 /* 115 * Allocate and init the vector, if it needs it. 116 * Also handle backwards compatibility. 117 */ 118 void 119 vfs_opv_init_explicit(vfs_opv_desc) 120 struct vnodeopv_desc *vfs_opv_desc; 121 { 122 int (**opv_desc_vector) __P((void *)); 123 struct vnodeopv_entry_desc *opve_descp; 124 125 opv_desc_vector = *(vfs_opv_desc->opv_desc_vector_p); 126 127 if (opv_desc_vector == NULL) { 128 /* XXX - shouldn't be M_VNODE */ 129 MALLOC(opv_desc_vector, PFI *, 130 vfs_opv_numops * sizeof(PFI), M_VNODE, M_WAITOK); 131 bzero(opv_desc_vector, vfs_opv_numops * sizeof(PFI)); 132 *(vfs_opv_desc->opv_desc_vector_p) = opv_desc_vector; 133 DODEBUG(printf("vector at %p allocated\n", 134 opv_desc_vector_p)); 135 } 136 137 for (opve_descp = vfs_opv_desc->opv_desc_ops; 138 opve_descp->opve_op; 139 opve_descp++) { 140 /* 141 * Sanity check: is this operation listed 142 * in the list of operations? We check this 143 * by seeing if its offest is zero. Since 144 * the default routine should always be listed 145 * first, it should be the only one with a zero 146 * offset. Any other operation with a zero 147 * offset is probably not listed in 148 * vfs_op_descs, and so is probably an error. 149 * 150 * A panic here means the layer programmer 151 * has committed the all-too common bug 152 * of adding a new operation to the layer's 153 * list of vnode operations but 154 * not adding the operation to the system-wide 155 * list of supported operations. 156 */ 157 if (opve_descp->opve_op->vdesc_offset == 0 && 158 opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) { 159 printf("operation %s not listed in %s.\n", 160 opve_descp->opve_op->vdesc_name, "vfs_op_descs"); 161 panic ("vfs_opv_init: bad operation"); 162 } 163 164 /* 165 * Fill in this entry. 166 */ 167 opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 168 opve_descp->opve_impl; 169 } 170 } 171 172 void 173 vfs_opv_init_default(vfs_opv_desc) 174 struct vnodeopv_desc *vfs_opv_desc; 175 { 176 int j; 177 int (**opv_desc_vector) __P((void *)); 178 179 opv_desc_vector = *(vfs_opv_desc->opv_desc_vector_p); 180 181 /* 182 * Force every operations vector to have a default routine. 183 */ 184 if (opv_desc_vector[VOFFSET(vop_default)] == NULL) 185 panic("vfs_opv_init: operation vector without default routine."); 186 187 for (j = 0; j < vfs_opv_numops; j++) 188 if (opv_desc_vector[j] == NULL) 189 opv_desc_vector[j] = 190 opv_desc_vector[VOFFSET(vop_default)]; 191 } 192 193 void 194 vfs_opv_init() 195 { 196 int i; 197 198 /* 199 * Allocate the dynamic vectors and fill them in. 200 */ 201 for (i = 0; vfs_opv_descs[i]; i++) 202 vfs_opv_init_explicit(vfs_opv_descs[i]); 203 204 /* 205 * Finally, go back and replace unfilled routines 206 * with their default. 207 */ 208 for (i = 0; vfs_opv_descs[i]; i++) 209 vfs_opv_init_default(vfs_opv_descs[i]); 210 } 211 212 /* 213 * Initialize known vnode operations vectors. 214 */ 215 void 216 vfs_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 */ 240 extern struct vnodeops dead_vnodeops; 241 extern struct vnodeops spec_vnodeops; 242 struct vattr va_null; 243 244 /* 245 * Initialize the vnode structures and initialize each file system type. 246 */ 247 void 248 vfsinit() 249 { 250 struct vfsops **vfsp; 251 252 /* 253 * Initialize the vnode table 254 */ 255 vntblinit(); 256 /* 257 * Initialize the vnode name cache 258 */ 259 nchinit(); 260 /* 261 * Build vnode operation vectors. 262 */ 263 vfs_op_init(); 264 vfs_opv_init(); /* finish the job */ 265 /* 266 * Initialize each file system type. 267 */ 268 vattr_null(&va_null); 269 for (vfsp = &vfssw[0]; vfsp < &vfssw[nvfssw]; vfsp++) { 270 if (*vfsp == NULL) 271 continue; 272 (*(*vfsp)->vfs_init)(); 273 } 274 } 275