vfs_init.c revision 40435
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from software contributed 61541Srgrimes * to Berkeley by John Heidemann of the UCLA Ficus project. 71541Srgrimes * 81541Srgrimes * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 3. All advertising materials mentioning features or use of this software 191541Srgrimes * must display the following acknowledgement: 201541Srgrimes * This product includes software developed by the University of 211541Srgrimes * California, Berkeley and its contributors. 221541Srgrimes * 4. Neither the name of the University nor the names of its contributors 231541Srgrimes * may be used to endorse or promote products derived from this software 241541Srgrimes * without specific prior written permission. 251541Srgrimes * 261541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 331541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 341541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361541Srgrimes * SUCH DAMAGE. 371541Srgrimes * 381541Srgrimes * @(#)vfs_init.c 8.3 (Berkeley) 1/4/94 3940435Speter * $Id: vfs_init.c,v 1.34 1998/10/05 11:10:55 obrien Exp $ 401541Srgrimes */ 411541Srgrimes 421541Srgrimes 431541Srgrimes#include <sys/param.h> 442112Swollman#include <sys/systm.h> 452946Swollman#include <sys/kernel.h> 461541Srgrimes#include <sys/mount.h> 4738869Sbde#include <sys/sysctl.h> 481541Srgrimes#include <sys/vnode.h> 491541Srgrimes#include <sys/malloc.h> 5029653Sdyson#include <vm/vm_zone.h> 511541Srgrimes 5212913Sphkstatic void vfs_op_init __P((void)); 5312577Sbde 5410653Sdgstatic void vfsinit __P((void *)); 5510358SjulianSYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL) 5610358Sjulian 5730354SphkMALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes"); 5830354Sphk 5910358Sjulian/* 601541Srgrimes * Sigh, such primitive tools are these... 611541Srgrimes */ 621541Srgrimes#if 0 631541Srgrimes#define DODEBUG(A) A 641541Srgrimes#else 651541Srgrimes#define DODEBUG(A) 661541Srgrimes#endif 671541Srgrimes 6833181Seivindstatic struct vfsconf void_vfsconf; 692946Swollman 7040435Speter#ifdef unused 712946Swollmanextern struct linker_set vfs_opv_descs_; 722946Swollman#define vfs_opv_descs ((struct vnodeopv_desc **)vfs_opv_descs_.ls_items) 7340435Speter#endif 742946Swollman 751541Srgrimesextern struct vnodeop_desc *vfs_op_descs[]; 761541Srgrimes /* and the operations they perform */ 771541Srgrimes 781541Srgrimes/* 7940435Speter * XXX this bloat just exands the sysctl__vfs linker set a little so that 8040435Speter * we can attach sysctls for VFS modules without expanding the linker set. 8140435Speter * Currently (1998/09/06), only one VFS uses sysctls, so 2 extra linker 8240435Speter * set slots are more than sufficient. 8340435Speter */ 8440435Speterextern struct linker_set sysctl__vfs; 8540435Speterstatic int mod_xx; 8640435SpeterSYSCTL_INT(_vfs, OID_AUTO, mod0, CTLFLAG_RD, &mod_xx, 0, ""); 8740435SpeterSYSCTL_INT(_vfs, OID_AUTO, mod1, CTLFLAG_RD, &mod_xx, 0, ""); 8840435Speter 8940435Speter/* 9029653Sdyson * Zone for namei 9129653Sdyson */ 9229653Sdysonstruct vm_zone *namei_zone; 9329653Sdyson 9429653Sdyson/* 951541Srgrimes * vfs_init.c 961541Srgrimes * 971541Srgrimes * Allocate and fill in operations vectors. 981541Srgrimes * 991541Srgrimes * An undocumented feature of this approach to defining operations is that 1001541Srgrimes * there can be multiple entries in vfs_opv_descs for the same operations 1011541Srgrimes * vector. This allows third parties to extend the set of operations 1021541Srgrimes * supported by another layer in a binary compatibile way. For example, 1031541Srgrimes * assume that NFS needed to be modified to support Ficus. NFS has an entry 1041541Srgrimes * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 1051541Srgrimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 1061541Srgrimes * listing those new operations Ficus adds to NFS, all without modifying the 1071541Srgrimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 1081541Srgrimes * that is a(whole)nother story.) This is a feature. 10929290Sphk * 11029290Sphk * Without an explicit reserve area, however, you must replace vnode_if.c 11129290Sphk * and vnode_if.h when you do this, or you will be derefrencing of the 11229290Sphk * end of vfs_op_descs[]. This is a flaw in the use of a structure 11329290Sphk * pointer array rather than an agregate to define vfs_op_descs. So 11429290Sphk * it's not a very dynamic "feature". 1151541Srgrimes */ 1161541Srgrimesvoid 11740435Spetervfs_opv_init(struct vnodeopv_desc *opv) 1181541Srgrimes{ 11940435Speter int j, k; 12012158Sbde vop_t ***opv_desc_vector_p; 12112158Sbde vop_t **opv_desc_vector; 1221541Srgrimes struct vnodeopv_entry_desc *opve_descp; 1231541Srgrimes 1241541Srgrimes /* 1251541Srgrimes * Allocate the dynamic vectors and fill them in. 1261541Srgrimes */ 12740435Speter opv_desc_vector_p = opv->opv_desc_vector_p; 12840435Speter /* 12940435Speter * Allocate and init the vector, if it needs it. 13040435Speter * Also handle backwards compatibility. 13140435Speter */ 13240435Speter if (*opv_desc_vector_p == NULL) { 13340435Speter /* XXX - shouldn't be M_VNODE */ 13440435Speter MALLOC(*opv_desc_vector_p, vop_t **, 13540435Speter vfs_opv_numops * sizeof(vop_t *), M_VNODE, 13640435Speter M_WAITOK); 13740435Speter bzero(*opv_desc_vector_p, 13840435Speter vfs_opv_numops * sizeof(vop_t *)); 13940435Speter DODEBUG(printf("vector at %x allocated\n", 14040435Speter opv_desc_vector_p)); 14140435Speter } 14240435Speter opv_desc_vector = *opv_desc_vector_p; 14340435Speter for (j = 0; opv->opv_desc_ops[j].opve_op; j++) { 14440435Speter opve_descp = &(opv->opv_desc_ops[j]); 14540435Speter 1461541Srgrimes /* 14740435Speter * Sanity check: is this operation listed 14840435Speter * in the list of operations? We check this 14940435Speter * by seeing if its offest is zero. Since 15040435Speter * the default routine should always be listed 15140435Speter * first, it should be the only one with a zero 15240435Speter * offset. Any other operation with a zero 15340435Speter * offset is probably not listed in 15440435Speter * vfs_op_descs, and so is probably an error. 15540435Speter * 15640435Speter * A panic here means the layer programmer 15740435Speter * has committed the all-too common bug 15840435Speter * of adding a new operation to the layer's 15940435Speter * list of vnode operations but 16040435Speter * not adding the operation to the system-wide 16140435Speter * list of supported operations. 1621541Srgrimes */ 16340435Speter if (opve_descp->opve_op->vdesc_offset == 0 && 16440435Speter opve_descp->opve_op->vdesc_offset != 16540435Speter VOFFSET(vop_default)) { 16640435Speter printf("operation %s not listed in %s.\n", 16740435Speter opve_descp->opve_op->vdesc_name, 16840435Speter "vfs_op_descs"); 16940435Speter panic ("vfs_opv_init: bad operation"); 1701541Srgrimes } 17140435Speter /* 17240435Speter * Fill in this entry. 17340435Speter */ 17440435Speter opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 17540435Speter opve_descp->opve_impl; 1761541Srgrimes } 1771541Srgrimes /* 1781541Srgrimes * Finally, go back and replace unfilled routines 1791541Srgrimes * with their default. (Sigh, an O(n^3) algorithm. I 1801541Srgrimes * could make it better, but that'd be work, and n is small.) 1811541Srgrimes */ 18240435Speter opv_desc_vector = *(opv->opv_desc_vector_p); 18340435Speter /* 18440435Speter * Force every operations vector to have a default routine. 18540435Speter */ 18640435Speter if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { 18740435Speter panic("vfs_opv_init: operation vector without default routine."); 1881541Srgrimes } 18940435Speter for (k = 0; k<vfs_opv_numops; k++) 19040435Speter if (opv_desc_vector[k] == NULL) 19140435Speter opv_desc_vector[k] = 19240435Speter opv_desc_vector[VOFFSET(vop_default)]; 1931541Srgrimes} 1941541Srgrimes 1951541Srgrimes/* 1961541Srgrimes * Initialize known vnode operations vectors. 1971541Srgrimes */ 19812913Sphkstatic void 1991541Srgrimesvfs_op_init() 2001541Srgrimes{ 2011541Srgrimes int i; 2021541Srgrimes 2031541Srgrimes DODEBUG(printf("Vnode_interface_init.\n")); 20429290Sphk DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops)); 20540435Speter#ifdef unused 2061541Srgrimes /* 2071541Srgrimes * Set all vnode vectors to a well known value. 2081541Srgrimes */ 2091541Srgrimes for (i = 0; vfs_opv_descs[i]; i++) 2101541Srgrimes *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL; 21140435Speter#endif 2121541Srgrimes /* 21329290Sphk * assign each op to its offset 21429290Sphk * 21529290Sphk * XXX This should not be needed, but is because the per 21629290Sphk * XXX FS ops tables are not sorted according to the 21729290Sphk * XXX vnodeop_desc's offset in vfs_op_descs. This 21829290Sphk * XXX is the same reason we have to take the hit for 21929290Sphk * XXX the static inline function calls instead of using 22029290Sphk * XXX simple macro references. 2211541Srgrimes */ 22229290Sphk for (i = 0; i < vfs_opv_numops; i++) 22329290Sphk vfs_op_descs[i]->vdesc_offset = i; 22440435Speter#ifdef unused 22540435Speter /* Finish the job */ 22640435Speter for (i = 0; vfs_opv_descs[i]; i++) 22740435Speter vfs_opv_init(vfs_opv_descs[i]); 22840435Speter#endif 2291541Srgrimes} 2301541Srgrimes 2311541Srgrimes/* 2321541Srgrimes * Routines having to do with the management of the vnode table. 2331541Srgrimes */ 2341541Srgrimesextern struct vnodeops dead_vnodeops; 2351541Srgrimesextern struct vnodeops spec_vnodeops; 2361541Srgrimesstruct vattr va_null; 2371541Srgrimes 2381541Srgrimes/* 2391541Srgrimes * Initialize the vnode structures and initialize each file system type. 2401541Srgrimes */ 24110358Sjulian/* ARGSUSED*/ 24210358Sjulianstatic void 24312569Sbdevfsinit(dummy) 24412569Sbde void *dummy; 2451541Srgrimes{ 24638869Sbde struct vfsconf **vfc, *vfsp; 24722521Sdyson int maxtypenum; 2481541Srgrimes 24929653Sdyson namei_zone = zinit("NAMEI", MAXPATHLEN, 0, 0, 2); 25029653Sdyson 2511541Srgrimes /* 2521541Srgrimes * Initialize the vnode table 2531541Srgrimes */ 2541541Srgrimes vntblinit(); 2551541Srgrimes /* 2561541Srgrimes * Initialize the vnode name cache 2571541Srgrimes */ 2581541Srgrimes nchinit(); 2591541Srgrimes /* 2601541Srgrimes * Build vnode operation vectors. 2611541Srgrimes */ 2621541Srgrimes vfs_op_init(); 2631541Srgrimes /* 2641541Srgrimes * Initialize each file system type. 26539975Sobrien * Vfs type numbers must be distinct from VFS_GENERIC (and VFS_VFSCONF). 2661541Srgrimes */ 2671541Srgrimes vattr_null(&va_null); 26840435Speter maxvfsconf = VFS_GENERIC + 1; 26940435Speter} 27040435Speter 27140435Speterint 27240435Spetervfs_register(vfc) 27340435Speter struct vfsconf *vfc; 27440435Speter{ 27540435Speter struct linker_set *l; 27640435Speter struct sysctl_oid **oidpp; 27740435Speter struct vfsconf *vfsp; 27840435Speter int error, i, maxtypenum, exists; 27940435Speter 28040435Speter vfsp = NULL; 28140435Speter exists = 0; 28240435Speter l = &sysctl__vfs; 28340435Speter if (vfsconf) 28440435Speter for (vfsp = vfsconf; vfsp->vfc_next; vfsp = vfsp->vfc_next) 28540435Speter if (!strcmp(vfc->vfc_name, vfsp->vfc_name)) 28640435Speter return EEXIST; 28740435Speter 28840435Speter vfc->vfc_typenum = maxvfsconf++; 28940435Speter if (vfc->vfc_vfsops->vfs_oid != NULL) { 29040435Speter oidpp = (struct sysctl_oid **)l->ls_items; 29140435Speter for (i = l->ls_length; i-- && !exists; oidpp++) 29240435Speter if (*oidpp == vfc->vfc_vfsops->vfs_oid) 29340435Speter exists = 1; 29440435Speter } 29540435Speter if (exists == 0 && vfc->vfc_vfsops->vfs_oid != NULL) { 29640435Speter oidpp = (struct sysctl_oid **)l->ls_items; 29740435Speter for (i = l->ls_length; i--; oidpp++) { 29840435Speter if (*oidpp == NULL || 29940435Speter *oidpp == &sysctl___vfs_mod0 || 30040435Speter *oidpp == &sysctl___vfs_mod1) { 30140435Speter *oidpp = vfc->vfc_vfsops->vfs_oid; 30240435Speter (*oidpp)->oid_number = vfc->vfc_typenum; 30340435Speter sysctl_order_all(); 30440435Speter break; 30540435Speter } 30638869Sbde } 3071541Srgrimes } 30840435Speter if (vfsp) 30940435Speter vfsp->vfc_next = vfc; 31040435Speter else 31140435Speter vfsconf = vfc; 31240435Speter vfc->vfc_next = NULL; 31340435Speter 31440435Speter /* 31540435Speter * Call init function for this VFS... 31640435Speter */ 31740435Speter (*(vfc->vfc_vfsops->vfs_init))(vfc); 31840435Speter 31940435Speter return 0; 3201541Srgrimes} 3212946Swollman 32240435Speter 32340435Speter/* 32440435Speter * To be called at SI_SUB_VFS, SECOND, for each VFS before any are registered. 32540435Speter */ 32640435Spetervoid 32740435Spetervfs_mod_opv_init(handle) 32840435Speter void *handle; 32940435Speter{ 33040435Speter int i; 33140435Speter struct vnodeopv_desc *opv; 33240435Speter 33340435Speter opv = (struct vnodeopv_desc *)handle; 33440435Speter *(opv->opv_desc_vector_p) = NULL; 33540435Speter vfs_opv_init(opv); 33640435Speter} 33740435Speter 33840435Speterint 33940435Spetervfs_unregister(vfc) 34040435Speter struct vfsconf *vfc; 34140435Speter{ 34240435Speter struct linker_set *l; 34340435Speter struct sysctl_oid **oidpp; 34440435Speter struct vfsconf *vfsp, *prev_vfsp; 34540435Speter int error, i, maxtypenum; 34640435Speter 34740435Speter i = vfc->vfc_typenum; 34840435Speter 34940435Speter prev_vfsp = NULL; 35040435Speter for (vfsp = vfsconf; vfsp; 35140435Speter prev_vfsp = vfsp, vfsp = vfsp->vfc_next) { 35240435Speter if (!strcmp(vfc->vfc_name, vfsp->vfc_name)) 35340435Speter break; 35440435Speter } 35540435Speter if (vfsp == NULL) 35640435Speter return EINVAL; 35740435Speter if (vfsp->vfc_refcount) 35840435Speter return EBUSY; 35940435Speter if (vfc->vfc_vfsops->vfs_uninit != NULL) { 36040435Speter error = (*vfc->vfc_vfsops->vfs_uninit)(vfsp); 36140435Speter if (error) 36240435Speter return (error); 36340435Speter } 36440435Speter if (prev_vfsp) 36540435Speter prev_vfsp->vfc_next = vfsp->vfc_next; 36640435Speter else 36740435Speter vfsconf = vfsp->vfc_next; 36840435Speter if (vfsp->vfc_vfsops->vfs_oid != NULL) { 36940435Speter l = &sysctl__vfs; 37040435Speter for (i = l->ls_length, 37140435Speter oidpp = (struct sysctl_oid **)l->ls_items; 37240435Speter i--; oidpp++) { 37340435Speter if (*oidpp == vfsp->vfc_vfsops->vfs_oid) { 37440435Speter *oidpp = NULL; 37540435Speter sysctl_order_all(); 37640435Speter break; 37740435Speter } 37840435Speter } 37940435Speter } 38040435Speter maxtypenum = VFS_GENERIC; 38140435Speter for (vfsp = vfsconf; vfsp != NULL; vfsp = vfsp->vfc_next) 38240435Speter if (maxtypenum < vfsp->vfc_typenum) 38340435Speter maxtypenum = vfsp->vfc_typenum; 38440435Speter maxvfsconf = maxtypenum + 1; 38540435Speter return 0; 38640435Speter} 387