vfs_init.c revision 111119
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 3950477Speter * $FreeBSD: head/sys/kern/vfs_init.c 111119 2003-02-19 05:47:46Z imp $ 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> 501541Srgrimes 5112577Sbde 5230354SphkMALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes"); 5330354Sphk 5410358Sjulian/* 5569664Speter * The highest defined VFS number. 5629653Sdyson */ 5769664Speterint maxvfsconf = VFS_GENERIC + 1; 5891690Seivind 5991690Seivind/* 6091690Seivind * Single-linked list of configured VFSes. 6191690Seivind * New entries are added/deleted by vfs_register()/vfs_unregister() 6291690Seivind */ 6352780Smsmithstruct vfsconf *vfsconf; 6452780Smsmith 6552780Smsmith/* 661541Srgrimes * vfs_init.c 671541Srgrimes * 681541Srgrimes * Allocate and fill in operations vectors. 691541Srgrimes * 701541Srgrimes * An undocumented feature of this approach to defining operations is that 711541Srgrimes * there can be multiple entries in vfs_opv_descs for the same operations 721541Srgrimes * vector. This allows third parties to extend the set of operations 731541Srgrimes * supported by another layer in a binary compatibile way. For example, 741541Srgrimes * assume that NFS needed to be modified to support Ficus. NFS has an entry 751541Srgrimes * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 761541Srgrimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 771541Srgrimes * listing those new operations Ficus adds to NFS, all without modifying the 781541Srgrimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 791541Srgrimes * that is a(whole)nother story.) This is a feature. 801541Srgrimes */ 8141056Speter 8241056Speter/* Table of known vnodeop vectors (list of VFS vnode vectors) */ 8343311Sdillonstatic const struct vnodeopv_desc **vnodeopv_descs; 8441056Speterstatic int vnodeopv_num; 8541056Speter 8641056Speter/* Table of known descs (list of vnode op handlers "vop_access_desc") */ 8741056Speterstatic struct vnodeop_desc **vfs_op_descs; 8891690Seivind/* Reference counts for vfs_op_descs */ 8991690Seivindstatic int *vfs_op_desc_refs; 9091690Seivind/* Number of descriptions */ 9141056Speterstatic int num_op_descs; 9291690Seivind/* Number of entries in each description */ 9395813Sdillonstatic int vfs_opv_numops = 64; 9441056Speter 9595813Sdillon/* Allow this number to be tuned at boot */ 9695813SdillonTUNABLE_INT("vfs.opv_numops", &vfs_opv_numops); 9795813SdillonSYSCTL_INT(_vfs, OID_AUTO, opv_numops, CTLFLAG_RD, &vfs_opv_numops, 9895813Sdillon 0, "Maximum number of operations in vop_t vector"); 9995813Sdillon 10095813Sdillonstatic int int_cmp(const void *a, const void *b); 10195813Sdillon 10295813Sdillonstatic int 10395813Sdillonint_cmp(const void *a, const void *b) 10495813Sdillon{ 10595813Sdillon return(*(const int *)a - *(const int *)b); 10695813Sdillon} 10795813Sdillon 10891690Seivind/* 10991690Seivind * Recalculate the operations vector/description (those parts of it that can 11091690Seivind * be recalculated, that is.) 11195813Sdillon * Always allocate operations vector large enough to hold vfs_opv_numops 11295813Sdillon * entries. The vector is never freed or deallocated once it is initialized, 11395813Sdillon * so that vnodes might safely reference it through their v_op pointer without 11495813Sdillon * vector changing suddenly from under them. 11591690Seivind */ 11641056Speterstatic void 11741056Spetervfs_opv_recalc(void) 1181541Srgrimes{ 11995813Sdillon int i, j, k; 12095813Sdillon int *vfs_op_offsets; 12112158Sbde vop_t ***opv_desc_vector_p; 12212158Sbde vop_t **opv_desc_vector; 1231541Srgrimes struct vnodeopv_entry_desc *opve_descp; 12443311Sdillon const struct vnodeopv_desc *opv; 1251541Srgrimes 12641056Speter if (vfs_op_descs == NULL) 12741056Speter panic("vfs_opv_recalc called with null vfs_op_descs"); 12841056Speter 1291541Srgrimes /* 13095813Sdillon * Allocate and initialize temporary array to store 13195813Sdillon * offsets. Sort it to put all uninitialized entries 13295813Sdillon * first and to make holes in existing offset sequence 13395813Sdillon * detectable. 13495813Sdillon */ 13595813Sdillon MALLOC(vfs_op_offsets, int *, 136111119Simp num_op_descs * sizeof(int), M_TEMP, M_WAITOK); 13795813Sdillon if (vfs_op_offsets == NULL) 13895813Sdillon panic("vfs_opv_recalc: no memory"); 13995813Sdillon for (i = 0; i < num_op_descs; i++) 14095813Sdillon vfs_op_offsets[i] = vfs_op_descs[i]->vdesc_offset; 14195813Sdillon qsort(vfs_op_offsets, num_op_descs, sizeof(int), int_cmp); 14295813Sdillon 14395813Sdillon /* 14495813Sdillon * Run through and make sure all known descs have an offset. 14595813Sdillon * Use vfs_op_offsets to locate holes in offset sequence and 14695813Sdillon * reuse them. 14741056Speter * vop_default_desc is hardwired at offset 1, and offset 0 14841056Speter * is a panic sanity check. 1491541Srgrimes */ 15095813Sdillon j = 1; k = 1; 15195813Sdillon for (i = 0; i < num_op_descs; i++) { 15295813Sdillon if (vfs_op_descs[i]->vdesc_offset != 0) 15395813Sdillon continue; 15495813Sdillon /* 15595813Sdillon * Look at two adjacent entries vfs_op_offsets[j - 1] and 15695813Sdillon * vfs_op_offsets[j] and see if we can fit a new offset 15795813Sdillon * number in between. If not, look at the next pair until 15895813Sdillon * hole is found or the end of the vfs_op_offsets vector is 15995813Sdillon * reached. j has been initialized to 1 above so that 16095813Sdillon * referencing (j-1)-th element is safe and the loop will 16195813Sdillon * never execute if num_op_descs is 1. For each new value s 16295813Sdillon * of i the j loop pick up from where previous iteration has 16395813Sdillon * left off. When the last hole has been consumed or if no 16495813Sdillon * hole has been found, we will start allocating new numbers 16595813Sdillon * starting from the biggest already available offset + 1. 16695813Sdillon */ 16795813Sdillon for (; j < num_op_descs; j++) { 16895813Sdillon if (vfs_op_offsets[j - 1] < k && vfs_op_offsets[j] > k) 16995813Sdillon break; 17095813Sdillon k = vfs_op_offsets[j] + 1; 17195813Sdillon } 17295813Sdillon vfs_op_descs[i]->vdesc_offset = k++; 17395813Sdillon } 17495813Sdillon FREE(vfs_op_offsets, M_TEMP); 17595813Sdillon 17695813Sdillon /* Panic if new vops will cause vector overflow */ 17795813Sdillon if (k > vfs_opv_numops) 17895813Sdillon panic("VFS: Ran out of vop_t vector entries. %d entries required, only %d available.\n", k, vfs_opv_numops); 17995813Sdillon 18040435Speter /* 18141056Speter * Allocate and fill in the vectors 18240435Speter */ 18341056Speter for (i = 0; i < vnodeopv_num; i++) { 18441056Speter opv = vnodeopv_descs[i]; 18541056Speter opv_desc_vector_p = opv->opv_desc_vector_p; 18641056Speter if (*opv_desc_vector_p == NULL) 18795813Sdillon MALLOC(*opv_desc_vector_p, vop_t **, 18895813Sdillon vfs_opv_numops * sizeof(vop_t *), M_VNODE, 189111119Simp M_WAITOK | M_ZERO); 19041056Speter 19165527Speter /* Fill in, with slot 0 being to return EOPNOTSUPP */ 19241056Speter opv_desc_vector = *opv_desc_vector_p; 19365527Speter opv_desc_vector[0] = (vop_t *)vop_eopnotsupp; 19441056Speter for (j = 0; opv->opv_desc_ops[j].opve_op; j++) { 19541056Speter opve_descp = &(opv->opv_desc_ops[j]); 19641056Speter opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 19741056Speter opve_descp->opve_impl; 19841056Speter } 19941056Speter 20041056Speter /* Replace unfilled routines with their default (slot 1). */ 20141056Speter opv_desc_vector = *(opv->opv_desc_vector_p); 20241056Speter if (opv_desc_vector[1] == NULL) 20341056Speter panic("vfs_opv_recalc: vector without a default."); 20441056Speter for (j = 0; j < vfs_opv_numops; j++) 20541056Speter if (opv_desc_vector[j] == NULL) 20641056Speter opv_desc_vector[j] = opv_desc_vector[1]; 20740435Speter } 20841056Speter} 20940435Speter 21091690Seivind/* Add a set of vnode operations (a description) to the table above. */ 21141056Spetervoid 21243311Sdillonvfs_add_vnodeops(const void *data) 21341056Speter{ 21443311Sdillon const struct vnodeopv_desc *opv; 21543311Sdillon const struct vnodeopv_desc **newopv; 21641056Speter struct vnodeop_desc **newop; 21741056Speter int *newref; 21841056Speter vop_t **opv_desc_vector; 21941056Speter struct vnodeop_desc *desc; 22041591Sarchie int i, j; 22141056Speter 22243311Sdillon opv = (const struct vnodeopv_desc *)data; 22343311Sdillon MALLOC(newopv, const struct vnodeopv_desc **, 224111119Simp (vnodeopv_num + 1) * sizeof(*newopv), M_VNODE, M_WAITOK); 22541056Speter if (vnodeopv_descs) { 22641056Speter bcopy(vnodeopv_descs, newopv, vnodeopv_num * sizeof(*newopv)); 22741056Speter FREE(vnodeopv_descs, M_VNODE); 22841056Speter } 22941056Speter newopv[vnodeopv_num] = opv; 23041056Speter vnodeopv_descs = newopv; 23141056Speter vnodeopv_num++; 23241056Speter 23341056Speter /* See if we have turned up a new vnode op desc */ 23441056Speter opv_desc_vector = *(opv->opv_desc_vector_p); 23541056Speter for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) { 23641056Speter for (j = 0; j < num_op_descs; j++) { 23741056Speter if (desc == vfs_op_descs[j]) { 23841056Speter /* found it, increase reference count */ 23941056Speter vfs_op_desc_refs[j]++; 24041056Speter break; 24141056Speter } 2421541Srgrimes } 24341056Speter if (j == num_op_descs) { 24441056Speter /* not found, new entry */ 24541056Speter MALLOC(newop, struct vnodeop_desc **, 24641056Speter (num_op_descs + 1) * sizeof(*newop), 247111119Simp M_VNODE, M_WAITOK); 24841056Speter /* new reference count (for unload) */ 24941056Speter MALLOC(newref, int *, 25041056Speter (num_op_descs + 1) * sizeof(*newref), 251111119Simp M_VNODE, M_WAITOK); 25241056Speter if (vfs_op_descs) { 25341056Speter bcopy(vfs_op_descs, newop, 25441056Speter num_op_descs * sizeof(*newop)); 25541056Speter FREE(vfs_op_descs, M_VNODE); 25641056Speter } 25741056Speter if (vfs_op_desc_refs) { 25841056Speter bcopy(vfs_op_desc_refs, newref, 25941056Speter num_op_descs * sizeof(*newref)); 26041056Speter FREE(vfs_op_desc_refs, M_VNODE); 26141056Speter } 26241056Speter newop[num_op_descs] = desc; 26341056Speter newref[num_op_descs] = 1; 26441056Speter vfs_op_descs = newop; 26541056Speter vfs_op_desc_refs = newref; 26641056Speter num_op_descs++; 26741056Speter } 2681541Srgrimes } 26941056Speter vfs_opv_recalc(); 2701541Srgrimes} 2711541Srgrimes 27291690Seivind/* Remove a vnode type from the vnode description table above. */ 27341056Spetervoid 27443311Sdillonvfs_rm_vnodeops(const void *data) 2751541Srgrimes{ 27643311Sdillon const struct vnodeopv_desc *opv; 27743311Sdillon const struct vnodeopv_desc **newopv; 27841056Speter struct vnodeop_desc **newop; 27941056Speter int *newref; 28041056Speter vop_t **opv_desc_vector; 28141056Speter struct vnodeop_desc *desc; 28241056Speter int i, j, k; 2831541Srgrimes 28443351Sdillon opv = (const struct vnodeopv_desc *)data; 28541056Speter /* Lower ref counts on descs in the table and release if zero */ 28641056Speter for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) { 28741056Speter for (j = 0; j < num_op_descs; j++) { 28841056Speter if (desc == vfs_op_descs[j]) { 28941056Speter /* found it, decrease reference count */ 29041056Speter vfs_op_desc_refs[j]--; 29141056Speter break; 29241056Speter } 29341056Speter } 29441056Speter for (j = 0; j < num_op_descs; j++) { 29541056Speter if (vfs_op_desc_refs[j] > 0) 29641056Speter continue; 29741056Speter if (vfs_op_desc_refs[j] < 0) 29841056Speter panic("vfs_remove_vnodeops: negative refcnt"); 29995813Sdillon /* Entry is going away - replace it with defaultop */ 30095813Sdillon for (k = 0; k < vnodeopv_num; k++) { 30195813Sdillon opv_desc_vector = 30295813Sdillon *(vnodeopv_descs[k]->opv_desc_vector_p); 30395813Sdillon if (opv_desc_vector != NULL) 30495813Sdillon opv_desc_vector[desc->vdesc_offset] = 30595813Sdillon opv_desc_vector[1]; 30695813Sdillon } 30741056Speter MALLOC(newop, struct vnodeop_desc **, 30841056Speter (num_op_descs - 1) * sizeof(*newop), 309111119Simp M_VNODE, M_WAITOK); 31041056Speter /* new reference count (for unload) */ 31141056Speter MALLOC(newref, int *, 31241056Speter (num_op_descs - 1) * sizeof(*newref), 313111119Simp M_VNODE, M_WAITOK); 31441056Speter for (k = j; k < (num_op_descs - 1); k++) { 31541056Speter vfs_op_descs[k] = vfs_op_descs[k + 1]; 31641056Speter vfs_op_desc_refs[k] = vfs_op_desc_refs[k + 1]; 31741056Speter } 31841056Speter bcopy(vfs_op_descs, newop, 31941056Speter (num_op_descs - 1) * sizeof(*newop)); 32041056Speter bcopy(vfs_op_desc_refs, newref, 32141056Speter (num_op_descs - 1) * sizeof(*newref)); 32241056Speter FREE(vfs_op_descs, M_VNODE); 32341056Speter FREE(vfs_op_desc_refs, M_VNODE); 32441056Speter vfs_op_descs = newop; 32541056Speter vfs_op_desc_refs = newref; 32641056Speter num_op_descs--; 32741056Speter } 32841056Speter } 32941056Speter 33041056Speter for (i = 0; i < vnodeopv_num; i++) { 33141056Speter if (vnodeopv_descs[i] == opv) { 33241056Speter for (j = i; j < (vnodeopv_num - 1); j++) 33341056Speter vnodeopv_descs[j] = vnodeopv_descs[j + 1]; 33441056Speter break; 33541056Speter } 33641056Speter } 33741056Speter if (i == vnodeopv_num) 33841056Speter panic("vfs_remove_vnodeops: opv not found"); 33995813Sdillon opv_desc_vector = *(opv->opv_desc_vector_p); 34095813Sdillon if (opv_desc_vector != NULL) 34195813Sdillon FREE(opv_desc_vector, M_VNODE); 34243311Sdillon MALLOC(newopv, const struct vnodeopv_desc **, 343111119Simp (vnodeopv_num - 1) * sizeof(*newopv), M_VNODE, M_WAITOK); 34441056Speter bcopy(vnodeopv_descs, newopv, (vnodeopv_num - 1) * sizeof(*newopv)); 34541056Speter FREE(vnodeopv_descs, M_VNODE); 34641056Speter vnodeopv_descs = newopv; 34741056Speter vnodeopv_num--; 34841056Speter 34941056Speter vfs_opv_recalc(); 3501541Srgrimes} 3511541Srgrimes 3521541Srgrimes/* 3531541Srgrimes * Routines having to do with the management of the vnode table. 3541541Srgrimes */ 3551541Srgrimesstruct vattr va_null; 3561541Srgrimes 3571541Srgrimes/* 35896755Strhodes * Initialize the vnode structures and initialize each filesystem type. 3591541Srgrimes */ 36010358Sjulian/* ARGSUSED*/ 36110358Sjulianstatic void 36241056Spetervfsinit(void *dummy) 3631541Srgrimes{ 3641541Srgrimes 3651541Srgrimes vattr_null(&va_null); 36640435Speter} 36741056SpeterSYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL) 36840435Speter 36996755Strhodes/* Register a new filesystem type in the global table */ 37040435Speterint 37141056Spetervfs_register(struct vfsconf *vfc) 37240435Speter{ 37344549Sdfr struct sysctl_oid *oidp; 37440435Speter struct vfsconf *vfsp; 37540435Speter 37640435Speter vfsp = NULL; 37740435Speter if (vfsconf) 37840435Speter for (vfsp = vfsconf; vfsp->vfc_next; vfsp = vfsp->vfc_next) 37944549Sdfr if (strcmp(vfc->vfc_name, vfsp->vfc_name) == 0) 38040435Speter return EEXIST; 38140435Speter 38240435Speter vfc->vfc_typenum = maxvfsconf++; 38340435Speter if (vfsp) 38440435Speter vfsp->vfc_next = vfc; 38540435Speter else 38640435Speter vfsconf = vfc; 38740435Speter vfc->vfc_next = NULL; 38840435Speter 38940435Speter /* 39044549Sdfr * If this filesystem has a sysctl node under vfs 39144549Sdfr * (i.e. vfs.xxfs), then change the oid number of that node to 39244549Sdfr * match the filesystem's type number. This allows user code 39344549Sdfr * which uses the type number to read sysctl variables defined 39444549Sdfr * by the filesystem to continue working. Since the oids are 39544549Sdfr * in a sorted list, we need to make sure the order is 39644549Sdfr * preserved by re-registering the oid after modifying its 39744549Sdfr * number. 39844549Sdfr */ 39972012Sphk SLIST_FOREACH(oidp, &sysctl__vfs_children, oid_link) 40044549Sdfr if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) { 40144549Sdfr sysctl_unregister_oid(oidp); 40244549Sdfr oidp->oid_number = vfc->vfc_typenum; 40344549Sdfr sysctl_register_oid(oidp); 40444549Sdfr } 40544549Sdfr 40644549Sdfr /* 40740435Speter * Call init function for this VFS... 40840435Speter */ 40940435Speter (*(vfc->vfc_vfsops->vfs_init))(vfc); 41040435Speter 41140435Speter return 0; 4121541Srgrimes} 4132946Swollman 41440435Speter 41596755Strhodes/* Remove registration of a filesystem type */ 41640435Speterint 41741056Spetervfs_unregister(struct vfsconf *vfc) 41840435Speter{ 41940435Speter struct vfsconf *vfsp, *prev_vfsp; 42040435Speter int error, i, maxtypenum; 42140435Speter 42240435Speter i = vfc->vfc_typenum; 42340435Speter 42440435Speter prev_vfsp = NULL; 42540435Speter for (vfsp = vfsconf; vfsp; 42640435Speter prev_vfsp = vfsp, vfsp = vfsp->vfc_next) { 42740435Speter if (!strcmp(vfc->vfc_name, vfsp->vfc_name)) 42840435Speter break; 42940435Speter } 43040435Speter if (vfsp == NULL) 43140435Speter return EINVAL; 43240435Speter if (vfsp->vfc_refcount) 43340435Speter return EBUSY; 43440435Speter if (vfc->vfc_vfsops->vfs_uninit != NULL) { 43540435Speter error = (*vfc->vfc_vfsops->vfs_uninit)(vfsp); 43640435Speter if (error) 43740435Speter return (error); 43840435Speter } 43940435Speter if (prev_vfsp) 44040435Speter prev_vfsp->vfc_next = vfsp->vfc_next; 44140435Speter else 44240435Speter vfsconf = vfsp->vfc_next; 44340435Speter maxtypenum = VFS_GENERIC; 44440435Speter for (vfsp = vfsconf; vfsp != NULL; vfsp = vfsp->vfc_next) 44540435Speter if (maxtypenum < vfsp->vfc_typenum) 44640435Speter maxtypenum = vfsp->vfc_typenum; 44740435Speter maxvfsconf = maxtypenum + 1; 44840435Speter return 0; 44940435Speter} 45041056Speter 45191690Seivind/* 45296755Strhodes * Standard kernel module handling code for filesystem modules. 45391690Seivind * Referenced from VFS_SET(). 45491690Seivind */ 45541056Speterint 45641170Sbdevfs_modevent(module_t mod, int type, void *data) 45741056Speter{ 45841056Speter struct vfsconf *vfc; 45941056Speter int error = 0; 46041056Speter 46141056Speter vfc = (struct vfsconf *)data; 46241056Speter 46341056Speter switch (type) { 46441056Speter case MOD_LOAD: 46541056Speter if (vfc) 46641056Speter error = vfs_register(vfc); 46741056Speter break; 46841056Speter 46941056Speter case MOD_UNLOAD: 47041056Speter if (vfc) 47141056Speter error = vfs_unregister(vfc); 47241056Speter break; 47341056Speter default: /* including MOD_SHUTDOWN */ 47441056Speter break; 47541056Speter } 47641056Speter return (error); 47741056Speter} 478