vfs_init.c revision 43351
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 3943351Sdillon * $Id: vfs_init.c,v 1.42 1999/01/28 00:57:47 dillon 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 5212577Sbde 5330354SphkMALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes"); 5430354Sphk 5510358Sjulian/* 5640435Speter * XXX this bloat just exands the sysctl__vfs linker set a little so that 5740435Speter * we can attach sysctls for VFS modules without expanding the linker set. 5840435Speter * Currently (1998/09/06), only one VFS uses sysctls, so 2 extra linker 5940435Speter * set slots are more than sufficient. 6040435Speter */ 6140435Speterextern struct linker_set sysctl__vfs; 6240435Speterstatic int mod_xx; 6340435SpeterSYSCTL_INT(_vfs, OID_AUTO, mod0, CTLFLAG_RD, &mod_xx, 0, ""); 6440435SpeterSYSCTL_INT(_vfs, OID_AUTO, mod1, CTLFLAG_RD, &mod_xx, 0, ""); 6540435Speter 6640435Speter/* 6729653Sdyson * Zone for namei 6829653Sdyson */ 6929653Sdysonstruct vm_zone *namei_zone; 7029653Sdyson 7129653Sdyson/* 721541Srgrimes * vfs_init.c 731541Srgrimes * 741541Srgrimes * Allocate and fill in operations vectors. 751541Srgrimes * 761541Srgrimes * An undocumented feature of this approach to defining operations is that 771541Srgrimes * there can be multiple entries in vfs_opv_descs for the same operations 781541Srgrimes * vector. This allows third parties to extend the set of operations 791541Srgrimes * supported by another layer in a binary compatibile way. For example, 801541Srgrimes * assume that NFS needed to be modified to support Ficus. NFS has an entry 811541Srgrimes * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 821541Srgrimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 831541Srgrimes * listing those new operations Ficus adds to NFS, all without modifying the 841541Srgrimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 851541Srgrimes * that is a(whole)nother story.) This is a feature. 861541Srgrimes */ 8741056Speter 8841056Speter/* Table of known vnodeop vectors (list of VFS vnode vectors) */ 8943311Sdillonstatic const struct vnodeopv_desc **vnodeopv_descs; 9041056Speterstatic int vnodeopv_num; 9141056Speter 9241056Speter/* Table of known descs (list of vnode op handlers "vop_access_desc") */ 9341056Speterstatic struct vnodeop_desc **vfs_op_descs; 9441056Speterstatic int *vfs_op_desc_refs; /* reference counts */ 9541056Speterstatic int num_op_descs; 9641056Speterstatic int vfs_opv_numops; 9741056Speter 9841056Speterstatic void 9941056Spetervfs_opv_recalc(void) 1001541Srgrimes{ 10141056Speter int i, j; 10212158Sbde vop_t ***opv_desc_vector_p; 10312158Sbde vop_t **opv_desc_vector; 1041541Srgrimes struct vnodeopv_entry_desc *opve_descp; 10543311Sdillon const struct vnodeopv_desc *opv; 1061541Srgrimes 10741056Speter if (vfs_op_descs == NULL) 10841056Speter panic("vfs_opv_recalc called with null vfs_op_descs"); 10941056Speter 1101541Srgrimes /* 11141056Speter * Run through and make sure all known descs have an offset 11241056Speter * 11341056Speter * vop_default_desc is hardwired at offset 1, and offset 0 11441056Speter * is a panic sanity check. 1151541Srgrimes */ 11641056Speter vfs_opv_numops = 0; 11741056Speter for (i = 0; i < num_op_descs; i++) 11841056Speter if (vfs_opv_numops < (vfs_op_descs[i]->vdesc_offset + 1)) 11941056Speter vfs_opv_numops = vfs_op_descs[i]->vdesc_offset + 1; 12041056Speter for (i = 0; i < num_op_descs; i++) 12141056Speter if (vfs_op_descs[i]->vdesc_offset == 0) 12241056Speter vfs_op_descs[i]->vdesc_offset = vfs_opv_numops++; 12340435Speter /* 12441056Speter * Allocate and fill in the vectors 12540435Speter */ 12641056Speter for (i = 0; i < vnodeopv_num; i++) { 12741056Speter opv = vnodeopv_descs[i]; 12841056Speter opv_desc_vector_p = opv->opv_desc_vector_p; 12941056Speter if (*opv_desc_vector_p) 13041056Speter FREE(*opv_desc_vector_p, M_VNODE); 13140435Speter MALLOC(*opv_desc_vector_p, vop_t **, 13240880Speter vfs_opv_numops * sizeof(vop_t *), M_VNODE, M_WAITOK); 13341056Speter if (*opv_desc_vector_p == NULL) 13441056Speter panic("no memory for vop_t ** vector"); 13541056Speter bzero(*opv_desc_vector_p, vfs_opv_numops * sizeof(vop_t *)); 13641056Speter 13741056Speter /* Fill in, with slot 0 being panic */ 13841056Speter opv_desc_vector = *opv_desc_vector_p; 13941056Speter opv_desc_vector[0] = (vop_t *)vop_panic; 14041056Speter for (j = 0; opv->opv_desc_ops[j].opve_op; j++) { 14141056Speter opve_descp = &(opv->opv_desc_ops[j]); 14241056Speter opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 14341056Speter opve_descp->opve_impl; 14441056Speter } 14541056Speter 14641056Speter /* Replace unfilled routines with their default (slot 1). */ 14741056Speter opv_desc_vector = *(opv->opv_desc_vector_p); 14841056Speter if (opv_desc_vector[1] == NULL) 14941056Speter panic("vfs_opv_recalc: vector without a default."); 15041056Speter for (j = 0; j < vfs_opv_numops; j++) 15141056Speter if (opv_desc_vector[j] == NULL) 15241056Speter opv_desc_vector[j] = opv_desc_vector[1]; 15340435Speter } 15441056Speter} 15540435Speter 15641056Spetervoid 15743311Sdillonvfs_add_vnodeops(const void *data) 15841056Speter{ 15943311Sdillon const struct vnodeopv_desc *opv; 16043311Sdillon const struct vnodeopv_desc **newopv; 16141056Speter struct vnodeop_desc **newop; 16241056Speter int *newref; 16341056Speter vop_t **opv_desc_vector; 16441056Speter struct vnodeop_desc *desc; 16541591Sarchie int i, j; 16641056Speter 16743311Sdillon opv = (const struct vnodeopv_desc *)data; 16843311Sdillon MALLOC(newopv, const struct vnodeopv_desc **, 16941056Speter (vnodeopv_num + 1) * sizeof(*newopv), M_VNODE, M_WAITOK); 17041056Speter if (newopv == NULL) 17141056Speter panic("vfs_add_vnodeops: no memory"); 17241056Speter if (vnodeopv_descs) { 17341056Speter bcopy(vnodeopv_descs, newopv, vnodeopv_num * sizeof(*newopv)); 17441056Speter FREE(vnodeopv_descs, M_VNODE); 17541056Speter } 17641056Speter newopv[vnodeopv_num] = opv; 17741056Speter vnodeopv_descs = newopv; 17841056Speter vnodeopv_num++; 17941056Speter 18041056Speter /* See if we have turned up a new vnode op desc */ 18141056Speter opv_desc_vector = *(opv->opv_desc_vector_p); 18241056Speter for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) { 18341056Speter for (j = 0; j < num_op_descs; j++) { 18441056Speter if (desc == vfs_op_descs[j]) { 18541056Speter /* found it, increase reference count */ 18641056Speter vfs_op_desc_refs[j]++; 18741056Speter break; 18841056Speter } 1891541Srgrimes } 19041056Speter if (j == num_op_descs) { 19141056Speter /* not found, new entry */ 19241056Speter MALLOC(newop, struct vnodeop_desc **, 19341056Speter (num_op_descs + 1) * sizeof(*newop), 19441056Speter M_VNODE, M_WAITOK); 19541056Speter if (newop == NULL) 19641056Speter panic("vfs_add_vnodeops: no memory for desc"); 19741056Speter /* new reference count (for unload) */ 19841056Speter MALLOC(newref, int *, 19941056Speter (num_op_descs + 1) * sizeof(*newref), 20041056Speter M_VNODE, M_WAITOK); 20141056Speter if (newref == NULL) 20241056Speter panic("vfs_add_vnodeops: no memory for refs"); 20341056Speter if (vfs_op_descs) { 20441056Speter bcopy(vfs_op_descs, newop, 20541056Speter num_op_descs * sizeof(*newop)); 20641056Speter FREE(vfs_op_descs, M_VNODE); 20741056Speter } 20841056Speter if (vfs_op_desc_refs) { 20941056Speter bcopy(vfs_op_desc_refs, newref, 21041056Speter num_op_descs * sizeof(*newref)); 21141056Speter FREE(vfs_op_desc_refs, M_VNODE); 21241056Speter } 21341056Speter newop[num_op_descs] = desc; 21441056Speter newref[num_op_descs] = 1; 21541056Speter vfs_op_descs = newop; 21641056Speter vfs_op_desc_refs = newref; 21741056Speter num_op_descs++; 21841056Speter } 2191541Srgrimes } 22041056Speter vfs_opv_recalc(); 2211541Srgrimes} 2221541Srgrimes 22341056Spetervoid 22443311Sdillonvfs_rm_vnodeops(const void *data) 2251541Srgrimes{ 22643311Sdillon const struct vnodeopv_desc *opv; 22743311Sdillon const struct vnodeopv_desc **newopv; 22841056Speter struct vnodeop_desc **newop; 22941056Speter int *newref; 23041056Speter vop_t **opv_desc_vector; 23141056Speter struct vnodeop_desc *desc; 23241056Speter int i, j, k; 2331541Srgrimes 23443351Sdillon opv = (const struct vnodeopv_desc *)data; 23541056Speter /* Lower ref counts on descs in the table and release if zero */ 23641056Speter opv_desc_vector = *(opv->opv_desc_vector_p); 23741056Speter for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) { 23841056Speter for (j = 0; j < num_op_descs; j++) { 23941056Speter if (desc == vfs_op_descs[j]) { 24041056Speter /* found it, decrease reference count */ 24141056Speter vfs_op_desc_refs[j]--; 24241056Speter break; 24341056Speter } 24441056Speter } 24541056Speter for (j = 0; j < num_op_descs; j++) { 24641056Speter if (vfs_op_desc_refs[j] > 0) 24741056Speter continue; 24841056Speter if (vfs_op_desc_refs[j] < 0) 24941056Speter panic("vfs_remove_vnodeops: negative refcnt"); 25041056Speter MALLOC(newop, struct vnodeop_desc **, 25141056Speter (num_op_descs - 1) * sizeof(*newop), 25241056Speter M_VNODE, M_WAITOK); 25341056Speter if (newop == NULL) 25441056Speter panic("vfs_remove_vnodeops: no memory for desc"); 25541056Speter /* new reference count (for unload) */ 25641056Speter MALLOC(newref, int *, 25741056Speter (num_op_descs - 1) * sizeof(*newref), 25841056Speter M_VNODE, M_WAITOK); 25941056Speter if (newref == NULL) 26041056Speter panic("vfs_remove_vnodeops: no memory for refs"); 26141056Speter for (k = j; k < (num_op_descs - 1); k++) { 26241056Speter vfs_op_descs[k] = vfs_op_descs[k + 1]; 26341056Speter vfs_op_desc_refs[k] = vfs_op_desc_refs[k + 1]; 26441056Speter } 26541056Speter bcopy(vfs_op_descs, newop, 26641056Speter (num_op_descs - 1) * sizeof(*newop)); 26741056Speter bcopy(vfs_op_desc_refs, newref, 26841056Speter (num_op_descs - 1) * sizeof(*newref)); 26941056Speter FREE(vfs_op_descs, M_VNODE); 27041056Speter FREE(vfs_op_desc_refs, M_VNODE); 27141056Speter vfs_op_descs = newop; 27241056Speter vfs_op_desc_refs = newref; 27341056Speter num_op_descs--; 27441056Speter } 27541056Speter } 27641056Speter 27741056Speter for (i = 0; i < vnodeopv_num; i++) { 27841056Speter if (vnodeopv_descs[i] == opv) { 27941056Speter for (j = i; j < (vnodeopv_num - 1); j++) 28041056Speter vnodeopv_descs[j] = vnodeopv_descs[j + 1]; 28141056Speter break; 28241056Speter } 28341056Speter } 28441056Speter if (i == vnodeopv_num) 28541056Speter panic("vfs_remove_vnodeops: opv not found"); 28643311Sdillon MALLOC(newopv, const struct vnodeopv_desc **, 28741056Speter (vnodeopv_num - 1) * sizeof(*newopv), M_VNODE, M_WAITOK); 28841056Speter if (newopv == NULL) 28941056Speter panic("vfs_remove_vnodeops: no memory"); 29041056Speter bcopy(vnodeopv_descs, newopv, (vnodeopv_num - 1) * sizeof(*newopv)); 29141056Speter FREE(vnodeopv_descs, M_VNODE); 29241056Speter vnodeopv_descs = newopv; 29341056Speter vnodeopv_num--; 29441056Speter 29541056Speter vfs_opv_recalc(); 2961541Srgrimes} 2971541Srgrimes 2981541Srgrimes/* 2991541Srgrimes * Routines having to do with the management of the vnode table. 3001541Srgrimes */ 3011541Srgrimesstruct vattr va_null; 3021541Srgrimes 3031541Srgrimes/* 3041541Srgrimes * Initialize the vnode structures and initialize each file system type. 3051541Srgrimes */ 30610358Sjulian/* ARGSUSED*/ 30710358Sjulianstatic void 30841056Spetervfsinit(void *dummy) 3091541Srgrimes{ 3101541Srgrimes 31129653Sdyson namei_zone = zinit("NAMEI", MAXPATHLEN, 0, 0, 2); 31229653Sdyson 3131541Srgrimes /* 3141541Srgrimes * Initialize the vnode table 3151541Srgrimes */ 3161541Srgrimes vntblinit(); 3171541Srgrimes /* 3181541Srgrimes * Initialize the vnode name cache 3191541Srgrimes */ 3201541Srgrimes nchinit(); 3211541Srgrimes /* 3221541Srgrimes * Initialize each file system type. 32339975Sobrien * Vfs type numbers must be distinct from VFS_GENERIC (and VFS_VFSCONF). 3241541Srgrimes */ 3251541Srgrimes vattr_null(&va_null); 32640435Speter maxvfsconf = VFS_GENERIC + 1; 32740435Speter} 32841056SpeterSYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL) 32940435Speter 33040435Speterint 33141056Spetervfs_register(struct vfsconf *vfc) 33240435Speter{ 33340435Speter struct linker_set *l; 33440435Speter struct sysctl_oid **oidpp; 33540435Speter struct vfsconf *vfsp; 33640648Sphk int i, exists; 33740435Speter 33840435Speter vfsp = NULL; 33940435Speter l = &sysctl__vfs; 34040435Speter if (vfsconf) 34140435Speter for (vfsp = vfsconf; vfsp->vfc_next; vfsp = vfsp->vfc_next) 34240435Speter if (!strcmp(vfc->vfc_name, vfsp->vfc_name)) 34340435Speter return EEXIST; 34440435Speter 34540435Speter vfc->vfc_typenum = maxvfsconf++; 34640435Speter if (vfc->vfc_vfsops->vfs_oid != NULL) { 34740637Sbde /* 34840637Sbde * Attach the oid to the "vfs" node of the sysctl tree if 34940637Sbde * it isn't already there (it will be there for statically 35040637Sbde * configured vfs's). 35140637Sbde */ 35240637Sbde exists = 0; 35340637Sbde for (i = l->ls_length, 35440637Sbde oidpp = (struct sysctl_oid **)l->ls_items; 35540637Sbde i-- != 0; oidpp++) 35640637Sbde if (*oidpp == vfc->vfc_vfsops->vfs_oid) { 35740435Speter exists = 1; 35840435Speter break; 35940435Speter } 36040637Sbde if (exists == 0) 36140637Sbde for (i = l->ls_length, 36240637Sbde oidpp = (struct sysctl_oid **)l->ls_items; 36340637Sbde i-- != 0; oidpp++) { 36440637Sbde if (*oidpp == NULL || 36540637Sbde *oidpp == &sysctl___vfs_mod0 || 36640637Sbde *oidpp == &sysctl___vfs_mod1) { 36740637Sbde *oidpp = vfc->vfc_vfsops->vfs_oid; 36840637Sbde break; 36940637Sbde } 37040637Sbde } 37140637Sbde 37240637Sbde vfc->vfc_vfsops->vfs_oid->oid_number = vfc->vfc_typenum; 37340637Sbde sysctl_order_all(); 3741541Srgrimes } 37540435Speter if (vfsp) 37640435Speter vfsp->vfc_next = vfc; 37740435Speter else 37840435Speter vfsconf = vfc; 37940435Speter vfc->vfc_next = NULL; 38040435Speter 38140435Speter /* 38240435Speter * Call init function for this VFS... 38340435Speter */ 38440435Speter (*(vfc->vfc_vfsops->vfs_init))(vfc); 38540435Speter 38640435Speter return 0; 3871541Srgrimes} 3882946Swollman 38940435Speter 39040435Speterint 39141056Spetervfs_unregister(struct vfsconf *vfc) 39240435Speter{ 39340435Speter struct linker_set *l; 39440435Speter struct sysctl_oid **oidpp; 39540435Speter struct vfsconf *vfsp, *prev_vfsp; 39640435Speter int error, i, maxtypenum; 39740435Speter 39840435Speter i = vfc->vfc_typenum; 39940435Speter 40040435Speter prev_vfsp = NULL; 40140435Speter for (vfsp = vfsconf; vfsp; 40240435Speter prev_vfsp = vfsp, vfsp = vfsp->vfc_next) { 40340435Speter if (!strcmp(vfc->vfc_name, vfsp->vfc_name)) 40440435Speter break; 40540435Speter } 40640435Speter if (vfsp == NULL) 40740435Speter return EINVAL; 40840435Speter if (vfsp->vfc_refcount) 40940435Speter return EBUSY; 41040435Speter if (vfc->vfc_vfsops->vfs_uninit != NULL) { 41140435Speter error = (*vfc->vfc_vfsops->vfs_uninit)(vfsp); 41240435Speter if (error) 41340435Speter return (error); 41440435Speter } 41540435Speter if (prev_vfsp) 41640435Speter prev_vfsp->vfc_next = vfsp->vfc_next; 41740435Speter else 41840435Speter vfsconf = vfsp->vfc_next; 41940435Speter if (vfsp->vfc_vfsops->vfs_oid != NULL) { 42040435Speter l = &sysctl__vfs; 42140435Speter for (i = l->ls_length, 42240435Speter oidpp = (struct sysctl_oid **)l->ls_items; 42340435Speter i--; oidpp++) { 42440435Speter if (*oidpp == vfsp->vfc_vfsops->vfs_oid) { 42540435Speter *oidpp = NULL; 42640435Speter sysctl_order_all(); 42740435Speter break; 42840435Speter } 42940435Speter } 43040435Speter } 43140435Speter maxtypenum = VFS_GENERIC; 43240435Speter for (vfsp = vfsconf; vfsp != NULL; vfsp = vfsp->vfc_next) 43340435Speter if (maxtypenum < vfsp->vfc_typenum) 43440435Speter maxtypenum = vfsp->vfc_typenum; 43540435Speter maxvfsconf = maxtypenum + 1; 43640435Speter return 0; 43740435Speter} 43841056Speter 43941056Speterint 44041170Sbdevfs_modevent(module_t mod, int type, void *data) 44141056Speter{ 44241056Speter struct vfsconf *vfc; 44341056Speter int error = 0; 44441056Speter 44541056Speter vfc = (struct vfsconf *)data; 44641056Speter 44741056Speter switch (type) { 44841056Speter case MOD_LOAD: 44941056Speter if (vfc) 45041056Speter error = vfs_register(vfc); 45141056Speter break; 45241056Speter 45341056Speter case MOD_UNLOAD: 45441056Speter if (vfc) 45541056Speter error = vfs_unregister(vfc); 45641056Speter break; 45741056Speter default: /* including MOD_SHUTDOWN */ 45841056Speter break; 45941056Speter } 46041056Speter return (error); 46141056Speter} 462