vfs_init.c revision 109623
1193323Sed/* 2193323Sed * Copyright (c) 1989, 1993 3193323Sed * The Regents of the University of California. All rights reserved. 4193323Sed * 5193323Sed * This code is derived from software contributed 6193323Sed * to Berkeley by John Heidemann of the UCLA Ficus project. 7193323Sed * 8193323Sed * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 9193323Sed * 10193323Sed * Redistribution and use in source and binary forms, with or without 11193323Sed * modification, are permitted provided that the following conditions 12193323Sed * are met: 13193323Sed * 1. Redistributions of source code must retain the above copyright 14193323Sed * notice, this list of conditions and the following disclaimer. 15193323Sed * 2. Redistributions in binary form must reproduce the above copyright 16193323Sed * notice, this list of conditions and the following disclaimer in the 17193323Sed * documentation and/or other materials provided with the distribution. 18252723Sdim * 3. All advertising materials mentioning features or use of this software 19193323Sed * must display the following acknowledgement: 20205218Srdivacky * This product includes software developed by the University of 21205218Srdivacky * California, Berkeley and its contributors. 22235633Sdim * 4. Neither the name of the University nor the names of its contributors 23252723Sdim * may be used to endorse or promote products derived from this software 24252723Sdim * without specific prior written permission. 25205407Srdivacky * 26205407Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30224145Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36193323Sed * SUCH DAMAGE. 37193323Sed * 38193323Sed * @(#)vfs_init.c 8.3 (Berkeley) 1/4/94 39198090Srdivacky * $FreeBSD: head/sys/kern/vfs_init.c 109623 2003-01-21 08:56:16Z alfred $ 40193323Sed */ 41198090Srdivacky 42198090Srdivacky 43198090Srdivacky#include <sys/param.h> 44198090Srdivacky#include <sys/systm.h> 45205218Srdivacky#include <sys/kernel.h> 46205218Srdivacky#include <sys/mount.h> 47205218Srdivacky#include <sys/sysctl.h> 48205218Srdivacky#include <sys/vnode.h> 49205218Srdivacky#include <sys/malloc.h> 50205218Srdivacky 51205218Srdivacky 52205218SrdivackyMALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes"); 53205218Srdivacky 54205218Srdivacky/* 55205218Srdivacky * The highest defined VFS number. 56205218Srdivacky */ 57205218Srdivackyint maxvfsconf = VFS_GENERIC + 1; 58205407Srdivacky 59205218Srdivacky/* 60205218Srdivacky * Single-linked list of configured VFSes. 61205218Srdivacky * New entries are added/deleted by vfs_register()/vfs_unregister() 62252723Sdim */ 63218893Sdimstruct vfsconf *vfsconf; 64205218Srdivacky 65218893Sdim/* 66205218Srdivacky * vfs_init.c 67205218Srdivacky * 68205218Srdivacky * Allocate and fill in operations vectors. 69205218Srdivacky * 70205218Srdivacky * An undocumented feature of this approach to defining operations is that 71205218Srdivacky * there can be multiple entries in vfs_opv_descs for the same operations 72218893Sdim * vector. This allows third parties to extend the set of operations 73205218Srdivacky * supported by another layer in a binary compatibile way. For example, 74205218Srdivacky * assume that NFS needed to be modified to support Ficus. NFS has an entry 75205218Srdivacky * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 76205218Srdivacky * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 77218893Sdim * listing those new operations Ficus adds to NFS, all without modifying the 78205218Srdivacky * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 79205218Srdivacky * that is a(whole)nother story.) This is a feature. 80205218Srdivacky */ 81218893Sdim 82205218Srdivacky/* Table of known vnodeop vectors (list of VFS vnode vectors) */ 83205218Srdivackystatic const struct vnodeopv_desc **vnodeopv_descs; 84205218Srdivackystatic int vnodeopv_num; 85205218Srdivacky 86218893Sdim/* Table of known descs (list of vnode op handlers "vop_access_desc") */ 87205407Srdivackystatic struct vnodeop_desc **vfs_op_descs; 88205407Srdivacky/* Reference counts for vfs_op_descs */ 89205407Srdivackystatic int *vfs_op_desc_refs; 90218893Sdim/* Number of descriptions */ 91205218Srdivackystatic int num_op_descs; 92205218Srdivacky/* Number of entries in each description */ 93205218Srdivackystatic int vfs_opv_numops = 64; 94218893Sdim 95205218Srdivacky/* Allow this number to be tuned at boot */ 96205218SrdivackyTUNABLE_INT("vfs.opv_numops", &vfs_opv_numops); 97205218SrdivackySYSCTL_INT(_vfs, OID_AUTO, opv_numops, CTLFLAG_RD, &vfs_opv_numops, 98218893Sdim 0, "Maximum number of operations in vop_t vector"); 99205218Srdivacky 100205218Srdivackystatic int int_cmp(const void *a, const void *b); 101205218Srdivacky 102218893Sdimstatic int 103205218Srdivackyint_cmp(const void *a, const void *b) 104205218Srdivacky{ 105218893Sdim return(*(const int *)a - *(const int *)b); 106205218Srdivacky} 107205218Srdivacky 108245431Sdim/* 109205218Srdivacky * Recalculate the operations vector/description (those parts of it that can 110193323Sed * be recalculated, that is.) 111205218Srdivacky * Always allocate operations vector large enough to hold vfs_opv_numops 112205218Srdivacky * entries. The vector is never freed or deallocated once it is initialized, 113205218Srdivacky * so that vnodes might safely reference it through their v_op pointer without 114193323Sed * vector changing suddenly from under them. 115205218Srdivacky */ 116205218Srdivackystatic void 117198090Srdivackyvfs_opv_recalc(void) 118205218Srdivacky{ 119205218Srdivacky int i, j, k; 120205218Srdivacky int *vfs_op_offsets; 121205218Srdivacky vop_t ***opv_desc_vector_p; 122205218Srdivacky vop_t **opv_desc_vector; 123205218Srdivacky struct vnodeopv_entry_desc *opve_descp; 124205218Srdivacky const struct vnodeopv_desc *opv; 125205218Srdivacky 126205218Srdivacky if (vfs_op_descs == NULL) 127205218Srdivacky panic("vfs_opv_recalc called with null vfs_op_descs"); 128205218Srdivacky 129205218Srdivacky /* 130218893Sdim * Allocate and initialize temporary array to store 131205218Srdivacky * offsets. Sort it to put all uninitialized entries 132205218Srdivacky * first and to make holes in existing offset sequence 133206083Srdivacky * detectable. 134218893Sdim */ 135218893Sdim MALLOC(vfs_op_offsets, int *, 136218893Sdim num_op_descs * sizeof(int), M_TEMP, 0); 137218893Sdim if (vfs_op_offsets == NULL) 138218893Sdim panic("vfs_opv_recalc: no memory"); 139205218Srdivacky for (i = 0; i < num_op_descs; i++) 140205218Srdivacky vfs_op_offsets[i] = vfs_op_descs[i]->vdesc_offset; 141218893Sdim qsort(vfs_op_offsets, num_op_descs, sizeof(int), int_cmp); 142205407Srdivacky 143205407Srdivacky /* 144205407Srdivacky * Run through and make sure all known descs have an offset. 145205407Srdivacky * Use vfs_op_offsets to locate holes in offset sequence and 146205407Srdivacky * reuse them. 147205407Srdivacky * vop_default_desc is hardwired at offset 1, and offset 0 148205407Srdivacky * is a panic sanity check. 149205218Srdivacky */ 150193323Sed j = 1; k = 1; 151193323Sed for (i = 0; i < num_op_descs; i++) { 152193323Sed if (vfs_op_descs[i]->vdesc_offset != 0) 153193323Sed continue; 154193323Sed /* 155193323Sed * Look at two adjacent entries vfs_op_offsets[j - 1] and 156193323Sed * vfs_op_offsets[j] and see if we can fit a new offset 157193323Sed * number in between. If not, look at the next pair until 158193323Sed * hole is found or the end of the vfs_op_offsets vector is 159218893Sdim * reached. j has been initialized to 1 above so that 160193323Sed * referencing (j-1)-th element is safe and the loop will 161218893Sdim * never execute if num_op_descs is 1. For each new value s 162218893Sdim * of i the j loop pick up from where previous iteration has 163218893Sdim * left off. When the last hole has been consumed or if no 164218893Sdim * hole has been found, we will start allocating new numbers 165193323Sed * starting from the biggest already available offset + 1. 166218893Sdim */ 167193323Sed for (; j < num_op_descs; j++) { 168193323Sed if (vfs_op_offsets[j - 1] < k && vfs_op_offsets[j] > k) 169205218Srdivacky break; 170193323Sed k = vfs_op_offsets[j] + 1; 171193323Sed } 172193323Sed vfs_op_descs[i]->vdesc_offset = k++; 173193323Sed } 174193323Sed FREE(vfs_op_offsets, M_TEMP); 175193323Sed 176193323Sed /* Panic if new vops will cause vector overflow */ 177193323Sed if (k > vfs_opv_numops) 178193323Sed panic("VFS: Ran out of vop_t vector entries. %d entries required, only %d available.\n", k, vfs_opv_numops); 179193323Sed 180193323Sed /* 181193323Sed * Allocate and fill in the vectors 182193323Sed */ 183218893Sdim for (i = 0; i < vnodeopv_num; i++) { 184218893Sdim opv = vnodeopv_descs[i]; 185218893Sdim opv_desc_vector_p = opv->opv_desc_vector_p; 186193323Sed if (*opv_desc_vector_p == NULL) 187193323Sed MALLOC(*opv_desc_vector_p, vop_t **, 188193323Sed vfs_opv_numops * sizeof(vop_t *), M_VNODE, 189193323Sed M_ZERO); 190245431Sdim 191245431Sdim /* Fill in, with slot 0 being to return EOPNOTSUPP */ 192193323Sed opv_desc_vector = *opv_desc_vector_p; 193193323Sed opv_desc_vector[0] = (vop_t *)vop_eopnotsupp; 194193323Sed for (j = 0; opv->opv_desc_ops[j].opve_op; j++) { 195193323Sed opve_descp = &(opv->opv_desc_ops[j]); 196193323Sed opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 197193323Sed opve_descp->opve_impl; 198193323Sed } 199193323Sed 200193323Sed /* Replace unfilled routines with their default (slot 1). */ 201193323Sed opv_desc_vector = *(opv->opv_desc_vector_p); 202193323Sed if (opv_desc_vector[1] == NULL) 203193323Sed panic("vfs_opv_recalc: vector without a default."); 204193323Sed for (j = 0; j < vfs_opv_numops; j++) 205193323Sed if (opv_desc_vector[j] == NULL) 206193323Sed opv_desc_vector[j] = opv_desc_vector[1]; 207193323Sed } 208193323Sed} 209218893Sdim 210193323Sed/* Add a set of vnode operations (a description) to the table above. */ 211218893Sdimvoid 212206083Srdivackyvfs_add_vnodeops(const void *data) 213206083Srdivacky{ 214193323Sed const struct vnodeopv_desc *opv; 215193323Sed const struct vnodeopv_desc **newopv; 216193323Sed struct vnodeop_desc **newop; 217193323Sed int *newref; 218218893Sdim vop_t **opv_desc_vector; 219193323Sed struct vnodeop_desc *desc; 220193323Sed int i, j; 221193323Sed 222218893Sdim opv = (const struct vnodeopv_desc *)data; 223204642Srdivacky MALLOC(newopv, const struct vnodeopv_desc **, 224204642Srdivacky (vnodeopv_num + 1) * sizeof(*newopv), M_VNODE, 0); 225205407Srdivacky if (vnodeopv_descs) { 226206083Srdivacky bcopy(vnodeopv_descs, newopv, vnodeopv_num * sizeof(*newopv)); 227218893Sdim FREE(vnodeopv_descs, M_VNODE); 228193323Sed } 229193323Sed newopv[vnodeopv_num] = opv; 230193323Sed vnodeopv_descs = newopv; 231193323Sed vnodeopv_num++; 232193323Sed 233193323Sed /* See if we have turned up a new vnode op desc */ 234193323Sed opv_desc_vector = *(opv->opv_desc_vector_p); 235245431Sdim for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) { 236193323Sed for (j = 0; j < num_op_descs; j++) { 237193323Sed if (desc == vfs_op_descs[j]) { 238193323Sed /* found it, increase reference count */ 239193323Sed vfs_op_desc_refs[j]++; 240193323Sed break; 241193323Sed } 242193323Sed } 243221345Sdim if (j == num_op_descs) { 244221345Sdim /* not found, new entry */ 245221345Sdim MALLOC(newop, struct vnodeop_desc **, 246221345Sdim (num_op_descs + 1) * sizeof(*newop), 247221345Sdim M_VNODE, 0); 248221345Sdim /* new reference count (for unload) */ 249221345Sdim MALLOC(newref, int *, 250221345Sdim (num_op_descs + 1) * sizeof(*newref), 251221345Sdim M_VNODE, 0); 252221345Sdim if (vfs_op_descs) { 253221345Sdim bcopy(vfs_op_descs, newop, 254193323Sed num_op_descs * sizeof(*newop)); 255221345Sdim FREE(vfs_op_descs, M_VNODE); 256221345Sdim } 257221345Sdim if (vfs_op_desc_refs) { 258221345Sdim bcopy(vfs_op_desc_refs, newref, 259221345Sdim num_op_descs * sizeof(*newref)); 260221345Sdim FREE(vfs_op_desc_refs, M_VNODE); 261221345Sdim } 262221345Sdim newop[num_op_descs] = desc; 263221345Sdim newref[num_op_descs] = 1; 264221345Sdim vfs_op_descs = newop; 265221345Sdim vfs_op_desc_refs = newref; 266221345Sdim num_op_descs++; 267221345Sdim } 268221345Sdim } 269221345Sdim vfs_opv_recalc(); 270221345Sdim} 271221345Sdim 272221345Sdim/* Remove a vnode type from the vnode description table above. */ 273221345Sdimvoid 274221345Sdimvfs_rm_vnodeops(const void *data) 275221345Sdim{ 276221345Sdim const struct vnodeopv_desc *opv; 277221345Sdim const struct vnodeopv_desc **newopv; 278221345Sdim struct vnodeop_desc **newop; 279221345Sdim int *newref; 280221345Sdim vop_t **opv_desc_vector; 281221345Sdim struct vnodeop_desc *desc; 282221345Sdim int i, j, k; 283221345Sdim 284221345Sdim opv = (const struct vnodeopv_desc *)data; 285221345Sdim /* Lower ref counts on descs in the table and release if zero */ 286221345Sdim for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) { 287221345Sdim for (j = 0; j < num_op_descs; j++) { 288221345Sdim if (desc == vfs_op_descs[j]) { 289221345Sdim /* found it, decrease reference count */ 290221345Sdim vfs_op_desc_refs[j]--; 291221345Sdim break; 292221345Sdim } 293221345Sdim } 294221345Sdim for (j = 0; j < num_op_descs; j++) { 295193323Sed if (vfs_op_desc_refs[j] > 0) 296193323Sed continue; 297193323Sed if (vfs_op_desc_refs[j] < 0) 298193323Sed panic("vfs_remove_vnodeops: negative refcnt"); 299205407Srdivacky /* Entry is going away - replace it with defaultop */ 300205407Srdivacky for (k = 0; k < vnodeopv_num; k++) { 301205407Srdivacky opv_desc_vector = 302205407Srdivacky *(vnodeopv_descs[k]->opv_desc_vector_p); 303218893Sdim if (opv_desc_vector != NULL) 304193323Sed opv_desc_vector[desc->vdesc_offset] = 305193323Sed opv_desc_vector[1]; 306193323Sed } 307218893Sdim MALLOC(newop, struct vnodeop_desc **, 308193323Sed (num_op_descs - 1) * sizeof(*newop), 309193323Sed M_VNODE, 0); 310193323Sed /* new reference count (for unload) */ 311218893Sdim MALLOC(newref, int *, 312193323Sed (num_op_descs - 1) * sizeof(*newref), 313193323Sed M_VNODE, 0); 314193323Sed for (k = j; k < (num_op_descs - 1); k++) { 315218893Sdim vfs_op_descs[k] = vfs_op_descs[k + 1]; 316193323Sed vfs_op_desc_refs[k] = vfs_op_desc_refs[k + 1]; 317193323Sed } 318221345Sdim bcopy(vfs_op_descs, newop, 319218893Sdim (num_op_descs - 1) * sizeof(*newop)); 320193323Sed bcopy(vfs_op_desc_refs, newref, 321193323Sed (num_op_descs - 1) * sizeof(*newref)); 322193323Sed FREE(vfs_op_descs, M_VNODE); 323218893Sdim FREE(vfs_op_desc_refs, M_VNODE); 324193323Sed vfs_op_descs = newop; 325193323Sed vfs_op_desc_refs = newref; 326205407Srdivacky num_op_descs--; 327218893Sdim } 328205407Srdivacky } 329205407Srdivacky 330205407Srdivacky for (i = 0; i < vnodeopv_num; i++) { 331205407Srdivacky if (vnodeopv_descs[i] == opv) { 332205218Srdivacky for (j = i; j < (vnodeopv_num - 1); j++) 333205407Srdivacky vnodeopv_descs[j] = vnodeopv_descs[j + 1]; 334193323Sed break; 335193323Sed } 336218893Sdim } 337252723Sdim if (i == vnodeopv_num) 338193323Sed panic("vfs_remove_vnodeops: opv not found"); 339206083Srdivacky opv_desc_vector = *(opv->opv_desc_vector_p); 340218893Sdim if (opv_desc_vector != NULL) 341193323Sed FREE(opv_desc_vector, M_VNODE); 342218893Sdim MALLOC(newopv, const struct vnodeopv_desc **, 343205218Srdivacky (vnodeopv_num - 1) * sizeof(*newopv), M_VNODE, 0); 344205407Srdivacky bcopy(vnodeopv_descs, newopv, (vnodeopv_num - 1) * sizeof(*newopv)); 345205407Srdivacky FREE(vnodeopv_descs, M_VNODE); 346205407Srdivacky vnodeopv_descs = newopv; 347205407Srdivacky vnodeopv_num--; 348205407Srdivacky 349205407Srdivacky vfs_opv_recalc(); 350205407Srdivacky} 351205407Srdivacky 352218893Sdim/* 353205407Srdivacky * Routines having to do with the management of the vnode table. 354205407Srdivacky */ 355205407Srdivackystruct vattr va_null; 356205407Srdivacky 357205407Srdivacky/* 358205407Srdivacky * Initialize the vnode structures and initialize each filesystem type. 359205407Srdivacky */ 360205407Srdivacky/* ARGSUSED*/ 361205407Srdivackystatic void 362218893Sdimvfsinit(void *dummy) 363193323Sed{ 364193323Sed 365218893Sdim vattr_null(&va_null); 366193323Sed} 367193323SedSYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL) 368193323Sed 369193323Sed/* Register a new filesystem type in the global table */ 370193323Sedint 371218893Sdimvfs_register(struct vfsconf *vfc) 372203954Srdivacky{ 373203954Srdivacky struct sysctl_oid *oidp; 374203954Srdivacky struct vfsconf *vfsp; 375203954Srdivacky 376203954Srdivacky vfsp = NULL; 377203954Srdivacky if (vfsconf) 378193323Sed for (vfsp = vfsconf; vfsp->vfc_next; vfsp = vfsp->vfc_next) 379221345Sdim if (strcmp(vfc->vfc_name, vfsp->vfc_name) == 0) 380221345Sdim return EEXIST; 381221345Sdim 382221345Sdim vfc->vfc_typenum = maxvfsconf++; 383221345Sdim if (vfsp) 384193323Sed vfsp->vfc_next = vfc; 385221345Sdim else 386193323Sed vfsconf = vfc; 387193323Sed vfc->vfc_next = NULL; 388193323Sed 389221345Sdim /* 390221345Sdim * If this filesystem has a sysctl node under vfs 391193323Sed * (i.e. vfs.xxfs), then change the oid number of that node to 392193323Sed * match the filesystem's type number. This allows user code 393193323Sed * which uses the type number to read sysctl variables defined 394193323Sed * by the filesystem to continue working. Since the oids are 395193323Sed * in a sorted list, we need to make sure the order is 396193323Sed * preserved by re-registering the oid after modifying its 397193323Sed * number. 398218893Sdim */ 399193323Sed SLIST_FOREACH(oidp, &sysctl__vfs_children, oid_link) 400193323Sed if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) { 401193323Sed sysctl_unregister_oid(oidp); 402193323Sed oidp->oid_number = vfc->vfc_typenum; 403203954Srdivacky sysctl_register_oid(oidp); 404203954Srdivacky } 405203954Srdivacky 406203954Srdivacky /* 407203954Srdivacky * Call init function for this VFS... 408203954Srdivacky */ 409203954Srdivacky (*(vfc->vfc_vfsops->vfs_init))(vfc); 410218893Sdim 411203954Srdivacky return 0; 412203954Srdivacky} 413203954Srdivacky 414218893Sdim 415193323Sed/* Remove registration of a filesystem type */ 416193323Sedint 417193323Sedvfs_unregister(struct vfsconf *vfc) 418218893Sdim{ 419195340Sed struct vfsconf *vfsp, *prev_vfsp; 420193323Sed int error, i, maxtypenum; 421218893Sdim 422193323Sed i = vfc->vfc_typenum; 423193323Sed 424193323Sed prev_vfsp = NULL; 425193323Sed for (vfsp = vfsconf; vfsp; 426193323Sed prev_vfsp = vfsp, vfsp = vfsp->vfc_next) { 427203954Srdivacky if (!strcmp(vfc->vfc_name, vfsp->vfc_name)) 428203954Srdivacky break; 429203954Srdivacky } 430218893Sdim if (vfsp == NULL) 431193323Sed return EINVAL; 432193323Sed if (vfsp->vfc_refcount) 433193323Sed return EBUSY; 434193323Sed if (vfc->vfc_vfsops->vfs_uninit != NULL) { 435193323Sed error = (*vfc->vfc_vfsops->vfs_uninit)(vfsp); 436193323Sed if (error) 437218893Sdim return (error); 438193323Sed } 439193323Sed if (prev_vfsp) 440193323Sed prev_vfsp->vfc_next = vfsp->vfc_next; 441193323Sed else 442193323Sed vfsconf = vfsp->vfc_next; 443193323Sed maxtypenum = VFS_GENERIC; 444193323Sed for (vfsp = vfsconf; vfsp != NULL; vfsp = vfsp->vfc_next) 445193323Sed if (maxtypenum < vfsp->vfc_typenum) 446193323Sed maxtypenum = vfsp->vfc_typenum; 447218893Sdim maxvfsconf = maxtypenum + 1; 448193323Sed return 0; 449193323Sed} 450245431Sdim 451193323Sed/* 452218893Sdim * Standard kernel module handling code for filesystem modules. 453193323Sed * Referenced from VFS_SET(). 454245431Sdim */ 455245431Sdimint 456193323Sedvfs_modevent(module_t mod, int type, void *data) 457205407Srdivacky{ 458205407Srdivacky struct vfsconf *vfc; 459205407Srdivacky int error = 0; 460193323Sed 461205218Srdivacky vfc = (struct vfsconf *)data; 462205407Srdivacky 463205407Srdivacky switch (type) { 464205407Srdivacky case MOD_LOAD: 465205218Srdivacky if (vfc) 466218893Sdim error = vfs_register(vfc); 467252723Sdim break; 468252723Sdim 469252723Sdim case MOD_UNLOAD: 470252723Sdim if (vfc) 471252723Sdim error = vfs_unregister(vfc); 472193323Sed break; 473193323Sed default: /* including MOD_SHUTDOWN */ 474193323Sed break; 475205407Srdivacky } 476205407Srdivacky return (error); 477218893Sdim} 478193323Sed