19454b2d8SWarner Losh /*- 2df8bae1dSRodney W. Grimes * Copyright (c) 1989, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * This code is derived from software contributed 6df8bae1dSRodney W. Grimes * to Berkeley by John Heidemann of the UCLA Ficus project. 7df8bae1dSRodney W. Grimes * 8df8bae1dSRodney W. Grimes * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 9df8bae1dSRodney W. Grimes * 10df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 11df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 12df8bae1dSRodney W. Grimes * are met: 13df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 15df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 16df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 17df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 18df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 19df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 20df8bae1dSRodney W. Grimes * without specific prior written permission. 21df8bae1dSRodney W. Grimes * 22df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32df8bae1dSRodney W. Grimes * SUCH DAMAGE. 33df8bae1dSRodney W. Grimes * 34df8bae1dSRodney W. Grimes * @(#)vfs_init.c 8.3 (Berkeley) 1/4/94 35df8bae1dSRodney W. Grimes */ 36df8bae1dSRodney W. Grimes 37677b542eSDavid E. O'Brien #include <sys/cdefs.h> 38677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 39df8bae1dSRodney W. Grimes 40df8bae1dSRodney W. Grimes #include <sys/param.h> 41f23b4c91SGarrett Wollman #include <sys/systm.h> 424d30adc4SRick Macklem #include <sys/fnv_hash.h> 43c901836cSGarrett Wollman #include <sys/kernel.h> 4432ba8e93SPoul-Henning Kamp #include <sys/linker.h> 45df8bae1dSRodney W. Grimes #include <sys/mount.h> 4632ba8e93SPoul-Henning Kamp #include <sys/proc.h> 47168f4ee0SKonstantin Belousov #include <sys/sx.h> 48edd32c2dSJohn Baldwin #include <sys/syscallsubr.h> 49e99ea9ecSBruce Evans #include <sys/sysctl.h> 50df8bae1dSRodney W. Grimes #include <sys/vnode.h> 51df8bae1dSRodney W. Grimes #include <sys/malloc.h> 52df8bae1dSRodney W. Grimes 53ebbfc2f8SPoul-Henning Kamp static int vfs_register(struct vfsconf *); 54ebbfc2f8SPoul-Henning Kamp static int vfs_unregister(struct vfsconf *); 552b14f991SJulian Elischer 56a1c995b6SPoul-Henning Kamp MALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes"); 57a1c995b6SPoul-Henning Kamp 582b14f991SJulian Elischer /* 59138e514cSPeter Wemm * The highest defined VFS number. 6099448ed1SJohn Dyson */ 61138e514cSPeter Wemm int maxvfsconf = VFS_GENERIC + 1; 62eb8e6d52SEivind Eklund 63eb8e6d52SEivind Eklund /* 64eb8e6d52SEivind Eklund * Single-linked list of configured VFSes. 65eb8e6d52SEivind Eklund * New entries are added/deleted by vfs_register()/vfs_unregister() 66eb8e6d52SEivind Eklund */ 673dfe213eSPoul-Henning Kamp struct vfsconfhead vfsconf = TAILQ_HEAD_INITIALIZER(vfsconf); 68168f4ee0SKonstantin Belousov struct sx vfsconf_sx; 69168f4ee0SKonstantin Belousov SX_SYSINIT(vfsconf, &vfsconf_sx, "vfsconf"); 70b676e48cSMike Smith 71b676e48cSMike Smith /* 724d30adc4SRick Macklem * Loader.conf variable vfs.typenumhash enables setting vfc_typenum using a hash 734d30adc4SRick Macklem * calculation on vfc_name, so that it doesn't change when file systems are 744d30adc4SRick Macklem * loaded in a different order. This will avoid the NFS server file handles from 754d30adc4SRick Macklem * changing for file systems that use vfc_typenum in their fsid. 764d30adc4SRick Macklem */ 774d30adc4SRick Macklem static int vfs_typenumhash = 1; 784d30adc4SRick Macklem SYSCTL_INT(_vfs, OID_AUTO, typenumhash, CTLFLAG_RDTUN, &vfs_typenumhash, 0, 794d30adc4SRick Macklem "Set vfc_typenum using a hash calculation on vfc_name, so that it does not" 804d30adc4SRick Macklem "change when file systems are loaded in a different order."); 814d30adc4SRick Macklem 824d30adc4SRick Macklem /* 83273350adSPoul-Henning Kamp * A Zen vnode attribute structure. 84273350adSPoul-Henning Kamp * 85273350adSPoul-Henning Kamp * Initialized when the first filesystem registers by vfs_register(). 86273350adSPoul-Henning Kamp */ 87273350adSPoul-Henning Kamp struct vattr va_null; 88273350adSPoul-Henning Kamp 89273350adSPoul-Henning Kamp /* 90df8bae1dSRodney W. Grimes * vfs_init.c 91df8bae1dSRodney W. Grimes * 92df8bae1dSRodney W. Grimes * Allocate and fill in operations vectors. 93df8bae1dSRodney W. Grimes * 94df8bae1dSRodney W. Grimes * An undocumented feature of this approach to defining operations is that 95df8bae1dSRodney W. Grimes * there can be multiple entries in vfs_opv_descs for the same operations 96df8bae1dSRodney W. Grimes * vector. This allows third parties to extend the set of operations 97df8bae1dSRodney W. Grimes * supported by another layer in a binary compatibile way. For example, 98df8bae1dSRodney W. Grimes * assume that NFS needed to be modified to support Ficus. NFS has an entry 99df8bae1dSRodney W. Grimes * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 100df8bae1dSRodney W. Grimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 101df8bae1dSRodney W. Grimes * listing those new operations Ficus adds to NFS, all without modifying the 102df8bae1dSRodney W. Grimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 103df8bae1dSRodney W. Grimes * that is a(whole)nother story.) This is a feature. 104df8bae1dSRodney W. Grimes */ 1054e61198eSPeter Wemm 106df8bae1dSRodney W. Grimes /* 107df8bae1dSRodney W. Grimes * Routines having to do with the management of the vnode table. 108df8bae1dSRodney W. Grimes */ 109df8bae1dSRodney W. Grimes 110168f4ee0SKonstantin Belousov static struct vfsconf * 111168f4ee0SKonstantin Belousov vfs_byname_locked(const char *name) 112168f4ee0SKonstantin Belousov { 113168f4ee0SKonstantin Belousov struct vfsconf *vfsp; 114168f4ee0SKonstantin Belousov 115168f4ee0SKonstantin Belousov sx_assert(&vfsconf_sx, SA_LOCKED); 116168f4ee0SKonstantin Belousov if (!strcmp(name, "ffs")) 117168f4ee0SKonstantin Belousov name = "ufs"; 118168f4ee0SKonstantin Belousov TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) { 119168f4ee0SKonstantin Belousov if (!strcmp(name, vfsp->vfc_name)) 120168f4ee0SKonstantin Belousov return (vfsp); 121168f4ee0SKonstantin Belousov } 122168f4ee0SKonstantin Belousov return (NULL); 123168f4ee0SKonstantin Belousov } 124168f4ee0SKonstantin Belousov 1253dfe213eSPoul-Henning Kamp struct vfsconf * 1263dfe213eSPoul-Henning Kamp vfs_byname(const char *name) 1273dfe213eSPoul-Henning Kamp { 1283dfe213eSPoul-Henning Kamp struct vfsconf *vfsp; 1293dfe213eSPoul-Henning Kamp 130168f4ee0SKonstantin Belousov vfsconf_slock(); 131168f4ee0SKonstantin Belousov vfsp = vfs_byname_locked(name); 132168f4ee0SKonstantin Belousov vfsconf_sunlock(); 1333dfe213eSPoul-Henning Kamp return (vfsp); 1343dfe213eSPoul-Henning Kamp } 1353dfe213eSPoul-Henning Kamp 13632ba8e93SPoul-Henning Kamp struct vfsconf * 13732ba8e93SPoul-Henning Kamp vfs_byname_kld(const char *fstype, struct thread *td, int *error) 13832ba8e93SPoul-Henning Kamp { 13932ba8e93SPoul-Henning Kamp struct vfsconf *vfsp; 140ffc72591SJamie Gritton int fileid, loaded; 14132ba8e93SPoul-Henning Kamp 14232ba8e93SPoul-Henning Kamp vfsp = vfs_byname(fstype); 14332ba8e93SPoul-Henning Kamp if (vfsp != NULL) 14432ba8e93SPoul-Henning Kamp return (vfsp); 14532ba8e93SPoul-Henning Kamp 146322fb40cSJohn Baldwin /* Try to load the respective module. */ 147edd32c2dSJohn Baldwin *error = kern_kldload(td, fstype, &fileid); 148ffc72591SJamie Gritton loaded = (*error == 0); 149ffc72591SJamie Gritton if (*error == EEXIST) 150ffc72591SJamie Gritton *error = 0; 15132ba8e93SPoul-Henning Kamp if (*error) 15232ba8e93SPoul-Henning Kamp return (NULL); 153edd32c2dSJohn Baldwin 15432ba8e93SPoul-Henning Kamp /* Look up again to see if the VFS was loaded. */ 15532ba8e93SPoul-Henning Kamp vfsp = vfs_byname(fstype); 15632ba8e93SPoul-Henning Kamp if (vfsp == NULL) { 157ffc72591SJamie Gritton if (loaded) 158edd32c2dSJohn Baldwin (void)kern_kldunload(td, fileid, LINKER_UNLOAD_FORCE); 15932ba8e93SPoul-Henning Kamp *error = ENODEV; 16032ba8e93SPoul-Henning Kamp return (NULL); 16132ba8e93SPoul-Henning Kamp } 16232ba8e93SPoul-Henning Kamp return (vfsp); 16332ba8e93SPoul-Henning Kamp } 16432ba8e93SPoul-Henning Kamp 16532ba8e93SPoul-Henning Kamp 166eb8e6d52SEivind Eklund /* Register a new filesystem type in the global table */ 167ebbfc2f8SPoul-Henning Kamp static int 1684e61198eSPeter Wemm vfs_register(struct vfsconf *vfc) 169aa855a59SPeter Wemm { 170a199ed3cSDoug Rabson struct sysctl_oid *oidp; 1717652131bSPoul-Henning Kamp struct vfsops *vfsops; 172273350adSPoul-Henning Kamp static int once; 1734d30adc4SRick Macklem struct vfsconf *tvfc; 1744d30adc4SRick Macklem uint32_t hashval; 1754d30adc4SRick Macklem int secondpass; 176273350adSPoul-Henning Kamp 177273350adSPoul-Henning Kamp if (!once) { 178273350adSPoul-Henning Kamp vattr_null(&va_null); 179273350adSPoul-Henning Kamp once = 1; 180273350adSPoul-Henning Kamp } 1817652131bSPoul-Henning Kamp 1825e8c582aSPoul-Henning Kamp if (vfc->vfc_version != VFS_VERSION) { 1835e8c582aSPoul-Henning Kamp printf("ERROR: filesystem %s, unsupported ABI version %x\n", 1845e8c582aSPoul-Henning Kamp vfc->vfc_name, vfc->vfc_version); 1855e8c582aSPoul-Henning Kamp return (EINVAL); 1865e8c582aSPoul-Henning Kamp } 187168f4ee0SKonstantin Belousov vfsconf_lock(); 188168f4ee0SKonstantin Belousov if (vfs_byname_locked(vfc->vfc_name) != NULL) { 189168f4ee0SKonstantin Belousov vfsconf_unlock(); 1905050aa86SKonstantin Belousov return (EEXIST); 191168f4ee0SKonstantin Belousov } 192aa855a59SPeter Wemm 1934d30adc4SRick Macklem if (vfs_typenumhash != 0) { 1944d30adc4SRick Macklem /* 1954d30adc4SRick Macklem * Calculate a hash on vfc_name to use for vfc_typenum. Unless 1964d30adc4SRick Macklem * all of 1<->255 are assigned, it is limited to 8bits since 1974d30adc4SRick Macklem * that is what ZFS uses from vfc_typenum and is also the 1984d30adc4SRick Macklem * preferred range for vfs_getnewfsid(). 1994d30adc4SRick Macklem */ 2004d30adc4SRick Macklem hashval = fnv_32_str(vfc->vfc_name, FNV1_32_INIT); 2014d30adc4SRick Macklem hashval &= 0xff; 2024d30adc4SRick Macklem secondpass = 0; 2034d30adc4SRick Macklem do { 2044d30adc4SRick Macklem /* Look for and fix any collision. */ 2054d30adc4SRick Macklem TAILQ_FOREACH(tvfc, &vfsconf, vfc_list) { 2064d30adc4SRick Macklem if (hashval == tvfc->vfc_typenum) { 2074d30adc4SRick Macklem if (hashval == 255 && secondpass == 0) { 2084d30adc4SRick Macklem hashval = 1; 2094d30adc4SRick Macklem secondpass = 1; 2104d30adc4SRick Macklem } else 2114d30adc4SRick Macklem hashval++; 2124d30adc4SRick Macklem break; 2134d30adc4SRick Macklem } 2144d30adc4SRick Macklem } 2154d30adc4SRick Macklem } while (tvfc != NULL); 2164d30adc4SRick Macklem vfc->vfc_typenum = hashval; 2174d30adc4SRick Macklem if (vfc->vfc_typenum >= maxvfsconf) 2184d30adc4SRick Macklem maxvfsconf = vfc->vfc_typenum + 1; 2194d30adc4SRick Macklem } else 220aa855a59SPeter Wemm vfc->vfc_typenum = maxvfsconf++; 2213dfe213eSPoul-Henning Kamp TAILQ_INSERT_TAIL(&vfsconf, vfc, vfc_list); 222aa855a59SPeter Wemm 223aa855a59SPeter Wemm /* 2247652131bSPoul-Henning Kamp * Initialise unused ``struct vfsops'' fields, to use 2257652131bSPoul-Henning Kamp * the vfs_std*() functions. Note, we need the mount 2267652131bSPoul-Henning Kamp * and unmount operations, at the least. The check 2277652131bSPoul-Henning Kamp * for vfsops available is just a debugging aid. 2287652131bSPoul-Henning Kamp */ 2297652131bSPoul-Henning Kamp KASSERT(vfc->vfc_vfsops != NULL, 2307652131bSPoul-Henning Kamp ("Filesystem %s has no vfsops", vfc->vfc_name)); 2317652131bSPoul-Henning Kamp /* 2327652131bSPoul-Henning Kamp * Check the mount and unmount operations. 2337652131bSPoul-Henning Kamp */ 2347652131bSPoul-Henning Kamp vfsops = vfc->vfc_vfsops; 23520a92a18SPoul-Henning Kamp KASSERT(vfsops->vfs_mount != NULL, 23620a92a18SPoul-Henning Kamp ("Filesystem %s has no mount op", vfc->vfc_name)); 2377652131bSPoul-Henning Kamp KASSERT(vfsops->vfs_unmount != NULL, 2387652131bSPoul-Henning Kamp ("Filesystem %s has no unmount op", vfc->vfc_name)); 2397652131bSPoul-Henning Kamp 2407652131bSPoul-Henning Kamp if (vfsops->vfs_root == NULL) 2417652131bSPoul-Henning Kamp /* return file system's root vnode */ 2427652131bSPoul-Henning Kamp vfsops->vfs_root = vfs_stdroot; 2437652131bSPoul-Henning Kamp if (vfsops->vfs_quotactl == NULL) 2447652131bSPoul-Henning Kamp /* quota control */ 2457652131bSPoul-Henning Kamp vfsops->vfs_quotactl = vfs_stdquotactl; 2467652131bSPoul-Henning Kamp if (vfsops->vfs_statfs == NULL) 2477652131bSPoul-Henning Kamp /* return file system's status */ 2487652131bSPoul-Henning Kamp vfsops->vfs_statfs = vfs_stdstatfs; 2497652131bSPoul-Henning Kamp if (vfsops->vfs_sync == NULL) 2507652131bSPoul-Henning Kamp /* 2517652131bSPoul-Henning Kamp * flush unwritten data (nosync) 2527652131bSPoul-Henning Kamp * file systems can use vfs_stdsync 2537652131bSPoul-Henning Kamp * explicitly by setting it in the 2547652131bSPoul-Henning Kamp * vfsop vector. 2557652131bSPoul-Henning Kamp */ 2567652131bSPoul-Henning Kamp vfsops->vfs_sync = vfs_stdnosync; 2577652131bSPoul-Henning Kamp if (vfsops->vfs_vget == NULL) 2587652131bSPoul-Henning Kamp /* convert an inode number to a vnode */ 2597652131bSPoul-Henning Kamp vfsops->vfs_vget = vfs_stdvget; 2607652131bSPoul-Henning Kamp if (vfsops->vfs_fhtovp == NULL) 2617652131bSPoul-Henning Kamp /* turn an NFS file handle into a vnode */ 2627652131bSPoul-Henning Kamp vfsops->vfs_fhtovp = vfs_stdfhtovp; 2637652131bSPoul-Henning Kamp if (vfsops->vfs_checkexp == NULL) 2647652131bSPoul-Henning Kamp /* check if file system is exported */ 2657652131bSPoul-Henning Kamp vfsops->vfs_checkexp = vfs_stdcheckexp; 2667652131bSPoul-Henning Kamp if (vfsops->vfs_init == NULL) 2677652131bSPoul-Henning Kamp /* file system specific initialisation */ 2687652131bSPoul-Henning Kamp vfsops->vfs_init = vfs_stdinit; 2697652131bSPoul-Henning Kamp if (vfsops->vfs_uninit == NULL) 2707652131bSPoul-Henning Kamp /* file system specific uninitialisation */ 2717652131bSPoul-Henning Kamp vfsops->vfs_uninit = vfs_stduninit; 2727652131bSPoul-Henning Kamp if (vfsops->vfs_extattrctl == NULL) 2737652131bSPoul-Henning Kamp /* extended attribute control */ 2747652131bSPoul-Henning Kamp vfsops->vfs_extattrctl = vfs_stdextattrctl; 27581d16e2dSAlfred Perlstein if (vfsops->vfs_sysctl == NULL) 27681d16e2dSAlfred Perlstein vfsops->vfs_sysctl = vfs_stdsysctl; 2777652131bSPoul-Henning Kamp 2787652131bSPoul-Henning Kamp /* 279aa855a59SPeter Wemm * Call init function for this VFS... 280aa855a59SPeter Wemm */ 281aa855a59SPeter Wemm (*(vfc->vfc_vfsops->vfs_init))(vfc); 282168f4ee0SKonstantin Belousov vfsconf_unlock(); 283aa855a59SPeter Wemm 284168f4ee0SKonstantin Belousov /* 285168f4ee0SKonstantin Belousov * If this filesystem has a sysctl node under vfs 286168f4ee0SKonstantin Belousov * (i.e. vfs.xxfs), then change the oid number of that node to 287168f4ee0SKonstantin Belousov * match the filesystem's type number. This allows user code 288168f4ee0SKonstantin Belousov * which uses the type number to read sysctl variables defined 289168f4ee0SKonstantin Belousov * by the filesystem to continue working. Since the oids are 290168f4ee0SKonstantin Belousov * in a sorted list, we need to make sure the order is 291168f4ee0SKonstantin Belousov * preserved by re-registering the oid after modifying its 292168f4ee0SKonstantin Belousov * number. 293168f4ee0SKonstantin Belousov */ 294580a0117SMateusz Guzik sysctl_xlock(); 295168f4ee0SKonstantin Belousov SLIST_FOREACH(oidp, SYSCTL_CHILDREN(&sysctl___vfs), oid_link) { 296168f4ee0SKonstantin Belousov if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) { 297168f4ee0SKonstantin Belousov sysctl_unregister_oid(oidp); 298168f4ee0SKonstantin Belousov oidp->oid_number = vfc->vfc_typenum; 299168f4ee0SKonstantin Belousov sysctl_register_oid(oidp); 300168f4ee0SKonstantin Belousov break; 301168f4ee0SKonstantin Belousov } 302168f4ee0SKonstantin Belousov } 303580a0117SMateusz Guzik sysctl_xunlock(); 304168f4ee0SKonstantin Belousov 305168f4ee0SKonstantin Belousov return (0); 306aa855a59SPeter Wemm } 307aa855a59SPeter Wemm 308aa855a59SPeter Wemm 309eb8e6d52SEivind Eklund /* Remove registration of a filesystem type */ 310ebbfc2f8SPoul-Henning Kamp static int 3114e61198eSPeter Wemm vfs_unregister(struct vfsconf *vfc) 312aa855a59SPeter Wemm { 3133dfe213eSPoul-Henning Kamp struct vfsconf *vfsp; 314*69baeadcSKonstantin Belousov int error, maxtypenum; 315aa855a59SPeter Wemm 316168f4ee0SKonstantin Belousov vfsconf_lock(); 317168f4ee0SKonstantin Belousov vfsp = vfs_byname_locked(vfc->vfc_name); 318168f4ee0SKonstantin Belousov if (vfsp == NULL) { 319168f4ee0SKonstantin Belousov vfsconf_unlock(); 320168f4ee0SKonstantin Belousov return (EINVAL); 321168f4ee0SKonstantin Belousov } 322168f4ee0SKonstantin Belousov if (vfsp->vfc_refcount != 0) { 323168f4ee0SKonstantin Belousov vfsconf_unlock(); 324168f4ee0SKonstantin Belousov return (EBUSY); 325168f4ee0SKonstantin Belousov } 326aa855a59SPeter Wemm if (vfc->vfc_vfsops->vfs_uninit != NULL) { 327aa855a59SPeter Wemm error = (*vfc->vfc_vfsops->vfs_uninit)(vfsp); 328168f4ee0SKonstantin Belousov if (error != 0) { 329168f4ee0SKonstantin Belousov vfsconf_unlock(); 330aa855a59SPeter Wemm return (error); 331aa855a59SPeter Wemm } 332168f4ee0SKonstantin Belousov } 3333dfe213eSPoul-Henning Kamp TAILQ_REMOVE(&vfsconf, vfsp, vfc_list); 334aa855a59SPeter Wemm maxtypenum = VFS_GENERIC; 3353dfe213eSPoul-Henning Kamp TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) 336aa855a59SPeter Wemm if (maxtypenum < vfsp->vfc_typenum) 337aa855a59SPeter Wemm maxtypenum = vfsp->vfc_typenum; 338aa855a59SPeter Wemm maxvfsconf = maxtypenum + 1; 339168f4ee0SKonstantin Belousov vfsconf_unlock(); 340168f4ee0SKonstantin Belousov return (0); 341aa855a59SPeter Wemm } 3424e61198eSPeter Wemm 343eb8e6d52SEivind Eklund /* 344eb8e6d52SEivind Eklund * Standard kernel module handling code for filesystem modules. 345eb8e6d52SEivind Eklund * Referenced from VFS_SET(). 346eb8e6d52SEivind Eklund */ 3474e61198eSPeter Wemm int 3484ae860afSBruce Evans vfs_modevent(module_t mod, int type, void *data) 3494e61198eSPeter Wemm { 3504e61198eSPeter Wemm struct vfsconf *vfc; 3514e61198eSPeter Wemm int error = 0; 3524e61198eSPeter Wemm 3534e61198eSPeter Wemm vfc = (struct vfsconf *)data; 3544e61198eSPeter Wemm 3554e61198eSPeter Wemm switch (type) { 3564e61198eSPeter Wemm case MOD_LOAD: 3574e61198eSPeter Wemm if (vfc) 3584e61198eSPeter Wemm error = vfs_register(vfc); 3594e61198eSPeter Wemm break; 3604e61198eSPeter Wemm 3614e61198eSPeter Wemm case MOD_UNLOAD: 3624e61198eSPeter Wemm if (vfc) 3634e61198eSPeter Wemm error = vfs_unregister(vfc); 3644e61198eSPeter Wemm break; 3653e019deaSPoul-Henning Kamp default: 3663e019deaSPoul-Henning Kamp error = EOPNOTSUPP; 3674e61198eSPeter Wemm break; 3684e61198eSPeter Wemm } 3694e61198eSPeter Wemm return (error); 3704e61198eSPeter Wemm } 371