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*65258Smckusick * @(#)vfs_init.c 8.2 (Berkeley) 12/30/93 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 struct vnodeop_defn *defnp; 8254289Smckusick int (***opv_desc_vector_p)(); 8354289Smckusick int (**opv_desc_vector)(); 8454289Smckusick struct vnodeopv_entry_desc *opve_descp; 8554289Smckusick 8654289Smckusick /* 8754289Smckusick * Allocate the dynamic vectors and fill them in. 8854289Smckusick */ 8954289Smckusick for (i=0; vfs_opv_descs[i]; i++) { 9054289Smckusick opv_desc_vector_p = vfs_opv_descs[i]->opv_desc_vector_p; 9154289Smckusick /* 9254289Smckusick * Allocate and init the vector, if it needs it. 9354289Smckusick * Also handle backwards compatibility. 9454289Smckusick */ 9554289Smckusick if (*opv_desc_vector_p == NULL) { 9654289Smckusick /* XXX - shouldn't be M_VNODE */ 9754289Smckusick MALLOC(*opv_desc_vector_p, PFI*, 9854289Smckusick vfs_opv_numops*sizeof(PFI), M_VNODE, M_WAITOK); 9954289Smckusick bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI)); 10054726Smckusick DODEBUG(printf("vector at %x allocated\n", 10154726Smckusick opv_desc_vector_p)); 10254726Smckusick } 10354289Smckusick opv_desc_vector = *opv_desc_vector_p; 10454289Smckusick for (j=0; vfs_opv_descs[i]->opv_desc_ops[j].opve_op; j++) { 10554289Smckusick opve_descp = &(vfs_opv_descs[i]->opv_desc_ops[j]); 10654289Smckusick 10754289Smckusick /* 10854289Smckusick * Sanity check: is this operation listed 10954289Smckusick * in the list of operations? We check this 11054289Smckusick * by seeing if its offest is zero. Since 11154289Smckusick * the default routine should always be listed 11254289Smckusick * first, it should be the only one with a zero 11354289Smckusick * offset. Any other operation with a zero 11454289Smckusick * offset is probably not listed in 11554726Smckusick * vfs_op_descs, and so is probably an error. 11654289Smckusick * 11754289Smckusick * A panic here means the layer programmer 11854289Smckusick * has committed the all-too common bug 11954289Smckusick * of adding a new operation to the layer's 12054289Smckusick * list of vnode operations but 12154289Smckusick * not adding the operation to the system-wide 12254289Smckusick * list of supported operations. 12354289Smckusick */ 12454289Smckusick if (opve_descp->opve_op->vdesc_offset == 0 && 12554289Smckusick opve_descp->opve_op->vdesc_offset != 12654289Smckusick VOFFSET(vop_default)) { 12754726Smckusick printf("operation %s not listed in %s.\n", 12854726Smckusick opve_descp->opve_op->vdesc_name, 12954726Smckusick "vfs_op_descs"); 13054289Smckusick panic ("vfs_opv_init: bad operation"); 13154726Smckusick } 13254289Smckusick /* 13354289Smckusick * Fill in this entry. 13454289Smckusick */ 13554726Smckusick opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 13654289Smckusick opve_descp->opve_impl; 13754726Smckusick } 13854726Smckusick } 13954289Smckusick /* 14054289Smckusick * Finally, go back and replace unfilled routines 14154289Smckusick * with their default. (Sigh, an O(n^3) algorithm. I 14254289Smckusick * could make it better, but that'd be work, and n is small.) 14354289Smckusick */ 14454726Smckusick for (i = 0; vfs_opv_descs[i]; i++) { 14554289Smckusick opv_desc_vector = *(vfs_opv_descs[i]->opv_desc_vector_p); 14654289Smckusick /* 14754289Smckusick * Force every operations vector to have a default routine. 14854289Smckusick */ 14954289Smckusick if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { 15054289Smckusick panic("vfs_opv_init: operation vector without default routine."); 15154726Smckusick } 15254726Smckusick for (k = 0; k<vfs_opv_numops; k++) 15354289Smckusick if (opv_desc_vector[k] == NULL) 15454289Smckusick opv_desc_vector[k] = 15554289Smckusick opv_desc_vector[VOFFSET(vop_default)]; 15654726Smckusick } 15754289Smckusick } 15854289Smckusick 15954726Smckusick /* 16054726Smckusick * Initialize known vnode operations vectors. 16154726Smckusick */ 16254289Smckusick void 16354289Smckusick vfs_op_init() 16454289Smckusick { 16554289Smckusick int i, j; 16654289Smckusick 16754726Smckusick DODEBUG(printf("Vnode_interface_init.\n")); 16854289Smckusick /* 16954289Smckusick * Set all vnode vectors to a well known value. 17054289Smckusick */ 17154726Smckusick for (i = 0; vfs_opv_descs[i]; i++) 17254289Smckusick *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL; 17354289Smckusick /* 17454289Smckusick * Figure out how many ops there are by counting the table, 17554289Smckusick * and assign each its offset. 17654289Smckusick */ 17754726Smckusick for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) { 17854289Smckusick vfs_op_descs[i]->vdesc_offset = vfs_opv_numops; 17954289Smckusick vfs_opv_numops++; 18054726Smckusick } 18154289Smckusick DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops)); 18254289Smckusick } 18354289Smckusick 18454289Smckusick /* 18554289Smckusick * Routines having to do with the management of the vnode table. 18654289Smckusick */ 18754289Smckusick extern struct vnodeops dead_vnodeops; 18854289Smckusick extern struct vnodeops spec_vnodeops; 18954289Smckusick extern void vclean(); 19054289Smckusick struct vattr va_null; 19154289Smckusick 19254289Smckusick /* 19354289Smckusick * Initialize the vnode structures and initialize each file system type. 19454289Smckusick */ 19554289Smckusick vfsinit() 19654289Smckusick { 19754289Smckusick struct vfsops **vfsp; 19854289Smckusick 19954289Smckusick /* 200*65258Smckusick * Initialize the vnode table 201*65258Smckusick */ 202*65258Smckusick vntblinit(); 203*65258Smckusick /* 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); 21654289Smckusick for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) { 21754289Smckusick if (*vfsp == NULL) 21854289Smckusick continue; 21954289Smckusick (*(*vfsp)->vfs_init)(); 22054289Smckusick } 22154289Smckusick } 222