154289Smckusick /* 254289Smckusick * Copyright (c) 1989 The Regents of the University of California. 354289Smckusick * 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*54726Smckusick * @(#)vfs_init.c 7.2 (Berkeley) 07/06/92 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/specdev.h> 2254289Smckusick #include <sys/namei.h> 2354289Smckusick #include <sys/ucred.h> 2454289Smckusick #include <sys/buf.h> 2554289Smckusick #include <sys/errno.h> 2654289Smckusick #include <sys/malloc.h> 2754289Smckusick 28*54726Smckusick /* 29*54726Smckusick * Sigh, such primitive tools are these... 30*54726Smckusick */ 3154289Smckusick #if 0 3254289Smckusick #define DODEBUG(A) A 3354289Smckusick #else 3454289Smckusick #define DODEBUG(A) 3554289Smckusick #endif 3654289Smckusick 3754289Smckusick extern struct vnodeopv_desc *vfs_opv_descs[]; 3854289Smckusick /* a list of lists of vnodeops defns */ 3954289Smckusick extern struct vnodeop_desc *vfs_op_descs[]; 4054289Smckusick /* and the operations they perform */ 4154289Smckusick /* 4254289Smckusick * This code doesn't work if the defn is **vnodop_defns with cc. 4354289Smckusick * The problem is because of the compiler sometimes putting in an 4454289Smckusick * extra level of indirection for arrays. It's an interesting 4554289Smckusick * "feature" of C. 4654289Smckusick */ 4754289Smckusick int vfs_opv_numops; 4854289Smckusick 4954289Smckusick typedef (*PFI)(); /* the standard Pointer to a Function returning an Int */ 5054289Smckusick 5154289Smckusick /* 5254289Smckusick * A miscellaneous routine. 5354289Smckusick * A generic "default" routine that just returns an error. 5454289Smckusick */ 5554289Smckusick int 5654289Smckusick vn_default_error() 5754289Smckusick { 58*54726Smckusick 59*54726Smckusick return (EOPNOTSUPP); 6054289Smckusick } 6154289Smckusick 6254289Smckusick /* 6354289Smckusick * vfs_init.c 6454289Smckusick * 6554289Smckusick * Allocate and fill in operations vectors. 6654289Smckusick * 67*54726Smckusick * An undocumented feature of this approach to defining operations is that 68*54726Smckusick * there can be multiple entries in vfs_opv_descs for the same operations 69*54726Smckusick * vector. This allows third parties to extend the set of operations 70*54726Smckusick * supported by another layer in a binary compatibile way. For example, 71*54726Smckusick * assume that NFS needed to be modified to support Ficus. NFS has an entry 72*54726Smckusick * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 73*54726Smckusick * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 74*54726Smckusick * listing those new operations Ficus adds to NFS, all without modifying the 75*54726Smckusick * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 76*54726Smckusick * that is a(whole)nother story.) This is a feature. 7754289Smckusick */ 7854289Smckusick void 7954289Smckusick vfs_opv_init() 8054289Smckusick { 8154289Smckusick int i, j, k; 8254289Smckusick struct vnodeop_defn *defnp; 8354289Smckusick int (***opv_desc_vector_p)(); 8454289Smckusick int (**opv_desc_vector)(); 8554289Smckusick struct vnodeopv_entry_desc *opve_descp; 8654289Smckusick 8754289Smckusick /* 8854289Smckusick * Allocate the dynamic vectors and fill them in. 8954289Smckusick */ 9054289Smckusick for (i=0; vfs_opv_descs[i]; i++) { 9154289Smckusick opv_desc_vector_p = vfs_opv_descs[i]->opv_desc_vector_p; 9254289Smckusick /* 9354289Smckusick * Allocate and init the vector, if it needs it. 9454289Smckusick * Also handle backwards compatibility. 9554289Smckusick */ 9654289Smckusick if (*opv_desc_vector_p == NULL) { 9754289Smckusick /* XXX - shouldn't be M_VNODE */ 9854289Smckusick MALLOC(*opv_desc_vector_p, PFI*, 9954289Smckusick vfs_opv_numops*sizeof(PFI), M_VNODE, M_WAITOK); 10054289Smckusick bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI)); 101*54726Smckusick DODEBUG(printf("vector at %x allocated\n", 102*54726Smckusick opv_desc_vector_p)); 103*54726Smckusick } 10454289Smckusick opv_desc_vector = *opv_desc_vector_p; 10554289Smckusick for (j=0; vfs_opv_descs[i]->opv_desc_ops[j].opve_op; j++) { 10654289Smckusick opve_descp = &(vfs_opv_descs[i]->opv_desc_ops[j]); 10754289Smckusick 10854289Smckusick /* 10954289Smckusick * Sanity check: is this operation listed 11054289Smckusick * in the list of operations? We check this 11154289Smckusick * by seeing if its offest is zero. Since 11254289Smckusick * the default routine should always be listed 11354289Smckusick * first, it should be the only one with a zero 11454289Smckusick * offset. Any other operation with a zero 11554289Smckusick * offset is probably not listed in 116*54726Smckusick * vfs_op_descs, and so is probably an error. 11754289Smckusick * 11854289Smckusick * A panic here means the layer programmer 11954289Smckusick * has committed the all-too common bug 12054289Smckusick * of adding a new operation to the layer's 12154289Smckusick * list of vnode operations but 12254289Smckusick * not adding the operation to the system-wide 12354289Smckusick * list of supported operations. 12454289Smckusick */ 12554289Smckusick if (opve_descp->opve_op->vdesc_offset == 0 && 12654289Smckusick opve_descp->opve_op->vdesc_offset != 12754289Smckusick VOFFSET(vop_default)) { 128*54726Smckusick printf("operation %s not listed in %s.\n", 129*54726Smckusick opve_descp->opve_op->vdesc_name, 130*54726Smckusick "vfs_op_descs"); 13154289Smckusick panic ("vfs_opv_init: bad operation"); 132*54726Smckusick } 13354289Smckusick /* 13454289Smckusick * Fill in this entry. 13554289Smckusick */ 136*54726Smckusick opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 13754289Smckusick opve_descp->opve_impl; 138*54726Smckusick } 139*54726Smckusick } 14054289Smckusick /* 14154289Smckusick * Finally, go back and replace unfilled routines 14254289Smckusick * with their default. (Sigh, an O(n^3) algorithm. I 14354289Smckusick * could make it better, but that'd be work, and n is small.) 14454289Smckusick */ 145*54726Smckusick for (i = 0; vfs_opv_descs[i]; i++) { 14654289Smckusick opv_desc_vector = *(vfs_opv_descs[i]->opv_desc_vector_p); 14754289Smckusick /* 14854289Smckusick * Force every operations vector to have a default routine. 14954289Smckusick */ 15054289Smckusick if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { 15154289Smckusick panic("vfs_opv_init: operation vector without default routine."); 152*54726Smckusick } 153*54726Smckusick for (k = 0; k<vfs_opv_numops; k++) 15454289Smckusick if (opv_desc_vector[k] == NULL) 15554289Smckusick opv_desc_vector[k] = 15654289Smckusick opv_desc_vector[VOFFSET(vop_default)]; 157*54726Smckusick } 15854289Smckusick } 15954289Smckusick 160*54726Smckusick /* 161*54726Smckusick * Initialize known vnode operations vectors. 162*54726Smckusick */ 16354289Smckusick void 16454289Smckusick vfs_op_init() 16554289Smckusick { 16654289Smckusick int i, j; 16754289Smckusick 168*54726Smckusick DODEBUG(printf("Vnode_interface_init.\n")); 16954289Smckusick /* 17054289Smckusick * Set all vnode vectors to a well known value. 17154289Smckusick */ 172*54726Smckusick for (i = 0; vfs_opv_descs[i]; i++) 17354289Smckusick *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL; 17454289Smckusick /* 17554289Smckusick * Figure out how many ops there are by counting the table, 17654289Smckusick * and assign each its offset. 17754289Smckusick */ 178*54726Smckusick for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) { 17954289Smckusick vfs_op_descs[i]->vdesc_offset = vfs_opv_numops; 18054289Smckusick vfs_opv_numops++; 181*54726Smckusick } 18254289Smckusick DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops)); 18354289Smckusick } 18454289Smckusick 18554289Smckusick /* 18654289Smckusick * Routines having to do with the management of the vnode table. 18754289Smckusick */ 18854289Smckusick struct vnode *vfreeh, **vfreet; 18954289Smckusick extern struct vnodeops dead_vnodeops; 19054289Smckusick extern struct vnodeops spec_vnodeops; 19154289Smckusick extern void vclean(); 19254289Smckusick struct vattr va_null; 19354289Smckusick 19454289Smckusick /* 19554289Smckusick * Initialize the vnode structures and initialize each file system type. 19654289Smckusick */ 19754289Smckusick vfsinit() 19854289Smckusick { 19954289Smckusick struct vfsops **vfsp; 20054289Smckusick 20154289Smckusick /* 20254289Smckusick * Initialize the vnode name cache 20354289Smckusick */ 20454289Smckusick nchinit(); 20554289Smckusick /* 20654289Smckusick * Build vnode operation vectors. 20754289Smckusick */ 20854289Smckusick vfs_op_init(); 20954289Smckusick vfs_opv_init(); /* finish the job */ 21054289Smckusick /* 21154289Smckusick * Initialize each file system type. 21254289Smckusick */ 21354289Smckusick vattr_null(&va_null); 21454289Smckusick for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) { 21554289Smckusick if (*vfsp == NULL) 21654289Smckusick continue; 21754289Smckusick (*(*vfsp)->vfs_init)(); 21854289Smckusick } 21954289Smckusick } 220