154289Smckusick /* 263180Sbostic * Copyright (c) 1989, 1993 363180Sbostic * The Regents of the University of California. All rights reserved. 454289Smckusick * 554289Smckusick * This code is derived from software contributed 654289Smckusick * to Berkeley by John Heidemann of the UCLA Ficus project. 754289Smckusick * 854289Smckusick * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 954289Smckusick * 1054289Smckusick * %sccs.include.redist.c% 1154289Smckusick * 12*68662Smckusick * @(#)vfs_init.c 8.4 (Berkeley) 03/30/95 1354289Smckusick */ 1454289Smckusick 1554289Smckusick 1654289Smckusick #include <sys/param.h> 1754289Smckusick #include <sys/mount.h> 1854289Smckusick #include <sys/time.h> 1954289Smckusick #include <sys/vnode.h> 2054289Smckusick #include <sys/stat.h> 2154289Smckusick #include <sys/namei.h> 2254289Smckusick #include <sys/ucred.h> 2354289Smckusick #include <sys/buf.h> 2454289Smckusick #include <sys/errno.h> 2554289Smckusick #include <sys/malloc.h> 2654289Smckusick 2754726Smckusick /* 2854726Smckusick * Sigh, such primitive tools are these... 2954726Smckusick */ 3054289Smckusick #if 0 3154289Smckusick #define DODEBUG(A) A 3254289Smckusick #else 3354289Smckusick #define DODEBUG(A) 3454289Smckusick #endif 3554289Smckusick 3654289Smckusick extern struct vnodeopv_desc *vfs_opv_descs[]; 3754289Smckusick /* a list of lists of vnodeops defns */ 3854289Smckusick extern struct vnodeop_desc *vfs_op_descs[]; 3954289Smckusick /* and the operations they perform */ 4054289Smckusick /* 4154289Smckusick * This code doesn't work if the defn is **vnodop_defns with cc. 4254289Smckusick * The problem is because of the compiler sometimes putting in an 4354289Smckusick * extra level of indirection for arrays. It's an interesting 4454289Smckusick * "feature" of C. 4554289Smckusick */ 4654289Smckusick int vfs_opv_numops; 4754289Smckusick 4854289Smckusick typedef (*PFI)(); /* the standard Pointer to a Function returning an Int */ 4954289Smckusick 5054289Smckusick /* 5154289Smckusick * A miscellaneous routine. 5254289Smckusick * A generic "default" routine that just returns an error. 5354289Smckusick */ 5454289Smckusick int 5554289Smckusick vn_default_error() 5654289Smckusick { 5754726Smckusick 5854726Smckusick return (EOPNOTSUPP); 5954289Smckusick } 6054289Smckusick 6154289Smckusick /* 6254289Smckusick * vfs_init.c 6354289Smckusick * 6454289Smckusick * Allocate and fill in operations vectors. 6554289Smckusick * 6654726Smckusick * An undocumented feature of this approach to defining operations is that 6754726Smckusick * there can be multiple entries in vfs_opv_descs for the same operations 6854726Smckusick * vector. This allows third parties to extend the set of operations 6954726Smckusick * supported by another layer in a binary compatibile way. For example, 7054726Smckusick * assume that NFS needed to be modified to support Ficus. NFS has an entry 7154726Smckusick * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 7254726Smckusick * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 7354726Smckusick * listing those new operations Ficus adds to NFS, all without modifying the 7454726Smckusick * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 7554726Smckusick * that is a(whole)nother story.) This is a feature. 7654289Smckusick */ 7754289Smckusick void 7854289Smckusick vfs_opv_init() 7954289Smckusick { 8054289Smckusick int i, j, k; 8154289Smckusick int (***opv_desc_vector_p)(); 8254289Smckusick int (**opv_desc_vector)(); 8354289Smckusick struct vnodeopv_entry_desc *opve_descp; 8454289Smckusick 8554289Smckusick /* 8654289Smckusick * Allocate the dynamic vectors and fill them in. 8754289Smckusick */ 8854289Smckusick for (i=0; vfs_opv_descs[i]; i++) { 8954289Smckusick opv_desc_vector_p = vfs_opv_descs[i]->opv_desc_vector_p; 9054289Smckusick /* 9154289Smckusick * Allocate and init the vector, if it needs it. 9254289Smckusick * Also handle backwards compatibility. 9354289Smckusick */ 9454289Smckusick if (*opv_desc_vector_p == NULL) { 9554289Smckusick /* XXX - shouldn't be M_VNODE */ 9654289Smckusick MALLOC(*opv_desc_vector_p, PFI*, 9754289Smckusick vfs_opv_numops*sizeof(PFI), M_VNODE, M_WAITOK); 9854289Smckusick bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI)); 9954726Smckusick DODEBUG(printf("vector at %x allocated\n", 10054726Smckusick opv_desc_vector_p)); 10154726Smckusick } 10254289Smckusick opv_desc_vector = *opv_desc_vector_p; 10354289Smckusick for (j=0; vfs_opv_descs[i]->opv_desc_ops[j].opve_op; j++) { 10454289Smckusick opve_descp = &(vfs_opv_descs[i]->opv_desc_ops[j]); 10554289Smckusick 10654289Smckusick /* 10754289Smckusick * Sanity check: is this operation listed 10854289Smckusick * in the list of operations? We check this 10954289Smckusick * by seeing if its offest is zero. Since 11054289Smckusick * the default routine should always be listed 11154289Smckusick * first, it should be the only one with a zero 11254289Smckusick * offset. Any other operation with a zero 11354289Smckusick * offset is probably not listed in 11454726Smckusick * vfs_op_descs, and so is probably an error. 11554289Smckusick * 11654289Smckusick * A panic here means the layer programmer 11754289Smckusick * has committed the all-too common bug 11854289Smckusick * of adding a new operation to the layer's 11954289Smckusick * list of vnode operations but 12054289Smckusick * not adding the operation to the system-wide 12154289Smckusick * list of supported operations. 12254289Smckusick */ 12354289Smckusick if (opve_descp->opve_op->vdesc_offset == 0 && 12454289Smckusick opve_descp->opve_op->vdesc_offset != 12554289Smckusick VOFFSET(vop_default)) { 12654726Smckusick printf("operation %s not listed in %s.\n", 12754726Smckusick opve_descp->opve_op->vdesc_name, 12854726Smckusick "vfs_op_descs"); 12954289Smckusick panic ("vfs_opv_init: bad operation"); 13054726Smckusick } 13154289Smckusick /* 13254289Smckusick * Fill in this entry. 13354289Smckusick */ 13454726Smckusick opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 13554289Smckusick opve_descp->opve_impl; 13654726Smckusick } 13754726Smckusick } 13854289Smckusick /* 13954289Smckusick * Finally, go back and replace unfilled routines 14054289Smckusick * with their default. (Sigh, an O(n^3) algorithm. I 14154289Smckusick * could make it better, but that'd be work, and n is small.) 14254289Smckusick */ 14354726Smckusick for (i = 0; vfs_opv_descs[i]; i++) { 14454289Smckusick opv_desc_vector = *(vfs_opv_descs[i]->opv_desc_vector_p); 14554289Smckusick /* 14654289Smckusick * Force every operations vector to have a default routine. 14754289Smckusick */ 14854289Smckusick if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { 14954289Smckusick panic("vfs_opv_init: operation vector without default routine."); 15054726Smckusick } 15154726Smckusick for (k = 0; k<vfs_opv_numops; k++) 15254289Smckusick if (opv_desc_vector[k] == NULL) 15354289Smckusick opv_desc_vector[k] = 15454289Smckusick opv_desc_vector[VOFFSET(vop_default)]; 15554726Smckusick } 15654289Smckusick } 15754289Smckusick 15854726Smckusick /* 15954726Smckusick * Initialize known vnode operations vectors. 16054726Smckusick */ 16154289Smckusick void 16254289Smckusick vfs_op_init() 16354289Smckusick { 16465443Sbostic int i; 16554289Smckusick 16654726Smckusick DODEBUG(printf("Vnode_interface_init.\n")); 16754289Smckusick /* 16854289Smckusick * Set all vnode vectors to a well known value. 16954289Smckusick */ 17054726Smckusick for (i = 0; vfs_opv_descs[i]; i++) 17154289Smckusick *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL; 17254289Smckusick /* 17354289Smckusick * Figure out how many ops there are by counting the table, 17454289Smckusick * and assign each its offset. 17554289Smckusick */ 17654726Smckusick for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) { 17754289Smckusick vfs_op_descs[i]->vdesc_offset = vfs_opv_numops; 17854289Smckusick vfs_opv_numops++; 17954726Smckusick } 18054289Smckusick DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops)); 18154289Smckusick } 18254289Smckusick 18354289Smckusick /* 18454289Smckusick * Routines having to do with the management of the vnode table. 18554289Smckusick */ 18654289Smckusick extern struct vnodeops dead_vnodeops; 18754289Smckusick extern struct vnodeops spec_vnodeops; 18854289Smckusick extern void vclean(); 18954289Smckusick struct vattr va_null; 19054289Smckusick 19154289Smckusick /* 19254289Smckusick * Initialize the vnode structures and initialize each file system type. 19354289Smckusick */ 19454289Smckusick vfsinit() 19554289Smckusick { 196*68662Smckusick struct vfsconf *vfsp; 197*68662Smckusick int i, maxtypenum; 19854289Smckusick 19954289Smckusick /* 20065258Smckusick * Initialize the vnode table 20165258Smckusick */ 20265258Smckusick vntblinit(); 20365258Smckusick /* 20454289Smckusick * Initialize the vnode name cache 20554289Smckusick */ 20654289Smckusick nchinit(); 20754289Smckusick /* 20854289Smckusick * Build vnode operation vectors. 20954289Smckusick */ 21054289Smckusick vfs_op_init(); 21154289Smckusick vfs_opv_init(); /* finish the job */ 21254289Smckusick /* 21354289Smckusick * Initialize each file system type. 21454289Smckusick */ 21554289Smckusick vattr_null(&va_null); 216*68662Smckusick maxtypenum = 0; 217*68662Smckusick for (vfsp = vfsconf, i = 1; i <= maxvfsconf; i++, vfsp++) { 218*68662Smckusick if (i < maxvfsconf) 219*68662Smckusick vfsp->vfc_next = vfsp + 1; 220*68662Smckusick if (maxtypenum <= vfsp->vfc_typenum) 221*68662Smckusick maxtypenum = vfsp->vfc_typenum + 1; 222*68662Smckusick (*vfsp->vfc_vfsops->vfs_init)(vfsp); 22354289Smckusick } 224*68662Smckusick /* next vfc_typenum to be used */ 225*68662Smckusick maxvfsconf = maxtypenum; 22654289Smckusick } 227