vfs_init.c revision 116271
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 391541Srgrimes */ 401541Srgrimes 41116182Sobrien#include <sys/cdefs.h> 42116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/vfs_init.c 116271 2003-06-12 20:48:38Z phk $"); 431541Srgrimes 441541Srgrimes#include <sys/param.h> 452112Swollman#include <sys/systm.h> 462946Swollman#include <sys/kernel.h> 471541Srgrimes#include <sys/mount.h> 4838869Sbde#include <sys/sysctl.h> 491541Srgrimes#include <sys/vnode.h> 501541Srgrimes#include <sys/malloc.h> 511541Srgrimes 5212577Sbde 5330354SphkMALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes"); 5430354Sphk 5510358Sjulian/* 5669664Speter * The highest defined VFS number. 5729653Sdyson */ 5869664Speterint maxvfsconf = VFS_GENERIC + 1; 5991690Seivind 6091690Seivind/* 6191690Seivind * Single-linked list of configured VFSes. 6291690Seivind * New entries are added/deleted by vfs_register()/vfs_unregister() 6391690Seivind */ 6452780Smsmithstruct vfsconf *vfsconf; 6552780Smsmith 6652780Smsmith/* 671541Srgrimes * vfs_init.c 681541Srgrimes * 691541Srgrimes * Allocate and fill in operations vectors. 701541Srgrimes * 711541Srgrimes * An undocumented feature of this approach to defining operations is that 721541Srgrimes * there can be multiple entries in vfs_opv_descs for the same operations 731541Srgrimes * vector. This allows third parties to extend the set of operations 741541Srgrimes * supported by another layer in a binary compatibile way. For example, 751541Srgrimes * assume that NFS needed to be modified to support Ficus. NFS has an entry 761541Srgrimes * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 771541Srgrimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 781541Srgrimes * listing those new operations Ficus adds to NFS, all without modifying the 791541Srgrimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 801541Srgrimes * that is a(whole)nother story.) This is a feature. 811541Srgrimes */ 8241056Speter 8341056Speter/* Table of known vnodeop vectors (list of VFS vnode vectors) */ 8443311Sdillonstatic const struct vnodeopv_desc **vnodeopv_descs; 8541056Speterstatic int vnodeopv_num; 8641056Speter 8741056Speter/* Table of known descs (list of vnode op handlers "vop_access_desc") */ 8841056Speterstatic struct vnodeop_desc **vfs_op_descs; 8991690Seivind/* Reference counts for vfs_op_descs */ 9091690Seivindstatic int *vfs_op_desc_refs; 9191690Seivind/* Number of descriptions */ 9241056Speterstatic int num_op_descs; 9391690Seivind/* Number of entries in each description */ 9495813Sdillonstatic int vfs_opv_numops = 64; 9541056Speter 9695813Sdillon/* Allow this number to be tuned at boot */ 9795813SdillonTUNABLE_INT("vfs.opv_numops", &vfs_opv_numops); 9895813SdillonSYSCTL_INT(_vfs, OID_AUTO, opv_numops, CTLFLAG_RD, &vfs_opv_numops, 9995813Sdillon 0, "Maximum number of operations in vop_t vector"); 10095813Sdillon 10195813Sdillonstatic int int_cmp(const void *a, const void *b); 10295813Sdillon 10395813Sdillonstatic int 10495813Sdillonint_cmp(const void *a, const void *b) 10595813Sdillon{ 10695813Sdillon return(*(const int *)a - *(const int *)b); 10795813Sdillon} 10895813Sdillon 10991690Seivind/* 11091690Seivind * Recalculate the operations vector/description (those parts of it that can 11191690Seivind * be recalculated, that is.) 11295813Sdillon * Always allocate operations vector large enough to hold vfs_opv_numops 11395813Sdillon * entries. The vector is never freed or deallocated once it is initialized, 11495813Sdillon * so that vnodes might safely reference it through their v_op pointer without 11595813Sdillon * vector changing suddenly from under them. 11691690Seivind */ 11741056Speterstatic void 11841056Spetervfs_opv_recalc(void) 1191541Srgrimes{ 12095813Sdillon int i, j, k; 12195813Sdillon int *vfs_op_offsets; 12212158Sbde vop_t ***opv_desc_vector_p; 12312158Sbde vop_t **opv_desc_vector; 1241541Srgrimes struct vnodeopv_entry_desc *opve_descp; 12543311Sdillon const struct vnodeopv_desc *opv; 1261541Srgrimes 12741056Speter if (vfs_op_descs == NULL) 12841056Speter panic("vfs_opv_recalc called with null vfs_op_descs"); 12941056Speter 1301541Srgrimes /* 13195813Sdillon * Allocate and initialize temporary array to store 13295813Sdillon * offsets. Sort it to put all uninitialized entries 13395813Sdillon * first and to make holes in existing offset sequence 13495813Sdillon * detectable. 13595813Sdillon */ 13695813Sdillon MALLOC(vfs_op_offsets, int *, 137111119Simp num_op_descs * sizeof(int), M_TEMP, M_WAITOK); 13895813Sdillon if (vfs_op_offsets == NULL) 13995813Sdillon panic("vfs_opv_recalc: no memory"); 14095813Sdillon for (i = 0; i < num_op_descs; i++) 14195813Sdillon vfs_op_offsets[i] = vfs_op_descs[i]->vdesc_offset; 14295813Sdillon qsort(vfs_op_offsets, num_op_descs, sizeof(int), int_cmp); 14395813Sdillon 14495813Sdillon /* 14595813Sdillon * Run through and make sure all known descs have an offset. 14695813Sdillon * Use vfs_op_offsets to locate holes in offset sequence and 14795813Sdillon * reuse them. 14841056Speter * vop_default_desc is hardwired at offset 1, and offset 0 14941056Speter * is a panic sanity check. 1501541Srgrimes */ 15195813Sdillon j = 1; k = 1; 15295813Sdillon for (i = 0; i < num_op_descs; i++) { 15395813Sdillon if (vfs_op_descs[i]->vdesc_offset != 0) 15495813Sdillon continue; 15595813Sdillon /* 15695813Sdillon * Look at two adjacent entries vfs_op_offsets[j - 1] and 15795813Sdillon * vfs_op_offsets[j] and see if we can fit a new offset 15895813Sdillon * number in between. If not, look at the next pair until 15995813Sdillon * hole is found or the end of the vfs_op_offsets vector is 16095813Sdillon * reached. j has been initialized to 1 above so that 16195813Sdillon * referencing (j-1)-th element is safe and the loop will 16295813Sdillon * never execute if num_op_descs is 1. For each new value s 16395813Sdillon * of i the j loop pick up from where previous iteration has 16495813Sdillon * left off. When the last hole has been consumed or if no 16595813Sdillon * hole has been found, we will start allocating new numbers 16695813Sdillon * starting from the biggest already available offset + 1. 16795813Sdillon */ 16895813Sdillon for (; j < num_op_descs; j++) { 16995813Sdillon if (vfs_op_offsets[j - 1] < k && vfs_op_offsets[j] > k) 17095813Sdillon break; 17195813Sdillon k = vfs_op_offsets[j] + 1; 17295813Sdillon } 17395813Sdillon vfs_op_descs[i]->vdesc_offset = k++; 17495813Sdillon } 17595813Sdillon FREE(vfs_op_offsets, M_TEMP); 17695813Sdillon 17795813Sdillon /* Panic if new vops will cause vector overflow */ 17895813Sdillon if (k > vfs_opv_numops) 17995813Sdillon panic("VFS: Ran out of vop_t vector entries. %d entries required, only %d available.\n", k, vfs_opv_numops); 18095813Sdillon 18140435Speter /* 18241056Speter * Allocate and fill in the vectors 18340435Speter */ 18441056Speter for (i = 0; i < vnodeopv_num; i++) { 18541056Speter opv = vnodeopv_descs[i]; 18641056Speter opv_desc_vector_p = opv->opv_desc_vector_p; 18741056Speter if (*opv_desc_vector_p == NULL) 18895813Sdillon MALLOC(*opv_desc_vector_p, vop_t **, 18995813Sdillon vfs_opv_numops * sizeof(vop_t *), M_VNODE, 190111119Simp M_WAITOK | M_ZERO); 19141056Speter 19265527Speter /* Fill in, with slot 0 being to return EOPNOTSUPP */ 19341056Speter opv_desc_vector = *opv_desc_vector_p; 19465527Speter opv_desc_vector[0] = (vop_t *)vop_eopnotsupp; 19541056Speter for (j = 0; opv->opv_desc_ops[j].opve_op; j++) { 19641056Speter opve_descp = &(opv->opv_desc_ops[j]); 19741056Speter opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 19841056Speter opve_descp->opve_impl; 19941056Speter } 20041056Speter 20141056Speter /* Replace unfilled routines with their default (slot 1). */ 20241056Speter opv_desc_vector = *(opv->opv_desc_vector_p); 20341056Speter if (opv_desc_vector[1] == NULL) 20441056Speter panic("vfs_opv_recalc: vector without a default."); 20541056Speter for (j = 0; j < vfs_opv_numops; j++) 20641056Speter if (opv_desc_vector[j] == NULL) 20741056Speter opv_desc_vector[j] = opv_desc_vector[1]; 20840435Speter } 20941056Speter} 21040435Speter 21191690Seivind/* Add a set of vnode operations (a description) to the table above. */ 21241056Spetervoid 21343311Sdillonvfs_add_vnodeops(const void *data) 21441056Speter{ 21543311Sdillon const struct vnodeopv_desc *opv; 21643311Sdillon const struct vnodeopv_desc **newopv; 21741056Speter struct vnodeop_desc **newop; 21841056Speter int *newref; 21941056Speter vop_t **opv_desc_vector; 22041056Speter struct vnodeop_desc *desc; 22141591Sarchie int i, j; 22241056Speter 22343311Sdillon opv = (const struct vnodeopv_desc *)data; 22443311Sdillon MALLOC(newopv, const struct vnodeopv_desc **, 225111119Simp (vnodeopv_num + 1) * sizeof(*newopv), M_VNODE, M_WAITOK); 22641056Speter if (vnodeopv_descs) { 22741056Speter bcopy(vnodeopv_descs, newopv, vnodeopv_num * sizeof(*newopv)); 22841056Speter FREE(vnodeopv_descs, M_VNODE); 22941056Speter } 23041056Speter newopv[vnodeopv_num] = opv; 23141056Speter vnodeopv_descs = newopv; 23241056Speter vnodeopv_num++; 23341056Speter 23441056Speter /* See if we have turned up a new vnode op desc */ 23541056Speter opv_desc_vector = *(opv->opv_desc_vector_p); 23641056Speter for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) { 23741056Speter for (j = 0; j < num_op_descs; j++) { 23841056Speter if (desc == vfs_op_descs[j]) { 23941056Speter /* found it, increase reference count */ 24041056Speter vfs_op_desc_refs[j]++; 24141056Speter break; 24241056Speter } 2431541Srgrimes } 24441056Speter if (j == num_op_descs) { 24541056Speter /* not found, new entry */ 24641056Speter MALLOC(newop, struct vnodeop_desc **, 24741056Speter (num_op_descs + 1) * sizeof(*newop), 248111119Simp M_VNODE, M_WAITOK); 24941056Speter /* new reference count (for unload) */ 25041056Speter MALLOC(newref, int *, 25141056Speter (num_op_descs + 1) * sizeof(*newref), 252111119Simp M_VNODE, M_WAITOK); 25341056Speter if (vfs_op_descs) { 25441056Speter bcopy(vfs_op_descs, newop, 25541056Speter num_op_descs * sizeof(*newop)); 25641056Speter FREE(vfs_op_descs, M_VNODE); 25741056Speter } 25841056Speter if (vfs_op_desc_refs) { 25941056Speter bcopy(vfs_op_desc_refs, newref, 26041056Speter num_op_descs * sizeof(*newref)); 26141056Speter FREE(vfs_op_desc_refs, M_VNODE); 26241056Speter } 26341056Speter newop[num_op_descs] = desc; 26441056Speter newref[num_op_descs] = 1; 26541056Speter vfs_op_descs = newop; 26641056Speter vfs_op_desc_refs = newref; 26741056Speter num_op_descs++; 26841056Speter } 2691541Srgrimes } 27041056Speter vfs_opv_recalc(); 2711541Srgrimes} 2721541Srgrimes 27391690Seivind/* Remove a vnode type from the vnode description table above. */ 27441056Spetervoid 27543311Sdillonvfs_rm_vnodeops(const void *data) 2761541Srgrimes{ 27743311Sdillon const struct vnodeopv_desc *opv; 27843311Sdillon const struct vnodeopv_desc **newopv; 27941056Speter struct vnodeop_desc **newop; 28041056Speter int *newref; 28141056Speter vop_t **opv_desc_vector; 28241056Speter struct vnodeop_desc *desc; 28341056Speter int i, j, k; 2841541Srgrimes 28543351Sdillon opv = (const struct vnodeopv_desc *)data; 28641056Speter /* Lower ref counts on descs in the table and release if zero */ 28741056Speter for (i = 0; (desc = opv->opv_desc_ops[i].opve_op); i++) { 28841056Speter for (j = 0; j < num_op_descs; j++) { 28941056Speter if (desc == vfs_op_descs[j]) { 29041056Speter /* found it, decrease reference count */ 29141056Speter vfs_op_desc_refs[j]--; 29241056Speter break; 29341056Speter } 29441056Speter } 29541056Speter for (j = 0; j < num_op_descs; j++) { 29641056Speter if (vfs_op_desc_refs[j] > 0) 29741056Speter continue; 29841056Speter if (vfs_op_desc_refs[j] < 0) 29941056Speter panic("vfs_remove_vnodeops: negative refcnt"); 30095813Sdillon /* Entry is going away - replace it with defaultop */ 30195813Sdillon for (k = 0; k < vnodeopv_num; k++) { 30295813Sdillon opv_desc_vector = 30395813Sdillon *(vnodeopv_descs[k]->opv_desc_vector_p); 30495813Sdillon if (opv_desc_vector != NULL) 30595813Sdillon opv_desc_vector[desc->vdesc_offset] = 30695813Sdillon opv_desc_vector[1]; 30795813Sdillon } 30841056Speter MALLOC(newop, struct vnodeop_desc **, 30941056Speter (num_op_descs - 1) * sizeof(*newop), 310111119Simp M_VNODE, M_WAITOK); 31141056Speter /* new reference count (for unload) */ 31241056Speter MALLOC(newref, int *, 31341056Speter (num_op_descs - 1) * sizeof(*newref), 314111119Simp M_VNODE, M_WAITOK); 31541056Speter for (k = j; k < (num_op_descs - 1); k++) { 31641056Speter vfs_op_descs[k] = vfs_op_descs[k + 1]; 31741056Speter vfs_op_desc_refs[k] = vfs_op_desc_refs[k + 1]; 31841056Speter } 31941056Speter bcopy(vfs_op_descs, newop, 32041056Speter (num_op_descs - 1) * sizeof(*newop)); 32141056Speter bcopy(vfs_op_desc_refs, newref, 32241056Speter (num_op_descs - 1) * sizeof(*newref)); 32341056Speter FREE(vfs_op_descs, M_VNODE); 32441056Speter FREE(vfs_op_desc_refs, M_VNODE); 32541056Speter vfs_op_descs = newop; 32641056Speter vfs_op_desc_refs = newref; 32741056Speter num_op_descs--; 32841056Speter } 32941056Speter } 33041056Speter 33141056Speter for (i = 0; i < vnodeopv_num; i++) { 33241056Speter if (vnodeopv_descs[i] == opv) { 33341056Speter for (j = i; j < (vnodeopv_num - 1); j++) 33441056Speter vnodeopv_descs[j] = vnodeopv_descs[j + 1]; 33541056Speter break; 33641056Speter } 33741056Speter } 33841056Speter if (i == vnodeopv_num) 33941056Speter panic("vfs_remove_vnodeops: opv not found"); 34095813Sdillon opv_desc_vector = *(opv->opv_desc_vector_p); 34195813Sdillon if (opv_desc_vector != NULL) 34295813Sdillon FREE(opv_desc_vector, M_VNODE); 34343311Sdillon MALLOC(newopv, const struct vnodeopv_desc **, 344111119Simp (vnodeopv_num - 1) * sizeof(*newopv), M_VNODE, M_WAITOK); 34541056Speter bcopy(vnodeopv_descs, newopv, (vnodeopv_num - 1) * sizeof(*newopv)); 34641056Speter FREE(vnodeopv_descs, M_VNODE); 34741056Speter vnodeopv_descs = newopv; 34841056Speter vnodeopv_num--; 34941056Speter 35041056Speter vfs_opv_recalc(); 3511541Srgrimes} 3521541Srgrimes 3531541Srgrimes/* 3541541Srgrimes * Routines having to do with the management of the vnode table. 3551541Srgrimes */ 3561541Srgrimesstruct vattr va_null; 3571541Srgrimes 3581541Srgrimes/* 35996755Strhodes * Initialize the vnode structures and initialize each filesystem type. 3601541Srgrimes */ 36110358Sjulian/* ARGSUSED*/ 36210358Sjulianstatic void 36341056Spetervfsinit(void *dummy) 3641541Srgrimes{ 3651541Srgrimes 3661541Srgrimes vattr_null(&va_null); 36740435Speter} 36841056SpeterSYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL) 36940435Speter 37096755Strhodes/* Register a new filesystem type in the global table */ 37140435Speterint 37241056Spetervfs_register(struct vfsconf *vfc) 37340435Speter{ 37444549Sdfr struct sysctl_oid *oidp; 37540435Speter struct vfsconf *vfsp; 37640435Speter 377116271Sphk struct vfsops *vfsops; 378116271Sphk 37940435Speter vfsp = NULL; 38040435Speter if (vfsconf) 38140435Speter for (vfsp = vfsconf; vfsp->vfc_next; vfsp = vfsp->vfc_next) 38244549Sdfr if (strcmp(vfc->vfc_name, vfsp->vfc_name) == 0) 38340435Speter return EEXIST; 38440435Speter 38540435Speter vfc->vfc_typenum = maxvfsconf++; 38640435Speter if (vfsp) 38740435Speter vfsp->vfc_next = vfc; 38840435Speter else 38940435Speter vfsconf = vfc; 39040435Speter vfc->vfc_next = NULL; 39140435Speter 39240435Speter /* 39344549Sdfr * If this filesystem has a sysctl node under vfs 39444549Sdfr * (i.e. vfs.xxfs), then change the oid number of that node to 39544549Sdfr * match the filesystem's type number. This allows user code 39644549Sdfr * which uses the type number to read sysctl variables defined 39744549Sdfr * by the filesystem to continue working. Since the oids are 39844549Sdfr * in a sorted list, we need to make sure the order is 39944549Sdfr * preserved by re-registering the oid after modifying its 40044549Sdfr * number. 40144549Sdfr */ 40272012Sphk SLIST_FOREACH(oidp, &sysctl__vfs_children, oid_link) 40344549Sdfr if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) { 40444549Sdfr sysctl_unregister_oid(oidp); 40544549Sdfr oidp->oid_number = vfc->vfc_typenum; 40644549Sdfr sysctl_register_oid(oidp); 40744549Sdfr } 40844549Sdfr 40944549Sdfr /* 410116271Sphk * Initialise unused ``struct vfsops'' fields, to use 411116271Sphk * the vfs_std*() functions. Note, we need the mount 412116271Sphk * and unmount operations, at the least. The check 413116271Sphk * for vfsops available is just a debugging aid. 414116271Sphk */ 415116271Sphk KASSERT(vfc->vfc_vfsops != NULL, 416116271Sphk ("Filesystem %s has no vfsops", vfc->vfc_name)); 417116271Sphk /* 418116271Sphk * Check the mount and unmount operations. 419116271Sphk */ 420116271Sphk vfsops = vfc->vfc_vfsops; 421116271Sphk KASSERT(vfsops->vfs_mount != NULL || vfsops->vfs_nmount != NULL, 422116271Sphk ("Filesystem %s has no (n)mount op", vfc->vfc_name)); 423116271Sphk KASSERT(vfsops->vfs_unmount != NULL, 424116271Sphk ("Filesystem %s has no unmount op", vfc->vfc_name)); 425116271Sphk 426116271Sphk if (vfsops->vfs_start == NULL) 427116271Sphk /* make a file system operational */ 428116271Sphk vfsops->vfs_start = vfs_stdstart; 429116271Sphk if (vfsops->vfs_root == NULL) 430116271Sphk /* return file system's root vnode */ 431116271Sphk vfsops->vfs_root = vfs_stdroot; 432116271Sphk if (vfsops->vfs_quotactl == NULL) 433116271Sphk /* quota control */ 434116271Sphk vfsops->vfs_quotactl = vfs_stdquotactl; 435116271Sphk if (vfsops->vfs_statfs == NULL) 436116271Sphk /* return file system's status */ 437116271Sphk vfsops->vfs_statfs = vfs_stdstatfs; 438116271Sphk if (vfsops->vfs_sync == NULL) 439116271Sphk /* 440116271Sphk * flush unwritten data (nosync) 441116271Sphk * file systems can use vfs_stdsync 442116271Sphk * explicitly by setting it in the 443116271Sphk * vfsop vector. 444116271Sphk */ 445116271Sphk vfsops->vfs_sync = vfs_stdnosync; 446116271Sphk if (vfsops->vfs_vget == NULL) 447116271Sphk /* convert an inode number to a vnode */ 448116271Sphk vfsops->vfs_vget = vfs_stdvget; 449116271Sphk if (vfsops->vfs_fhtovp == NULL) 450116271Sphk /* turn an NFS file handle into a vnode */ 451116271Sphk vfsops->vfs_fhtovp = vfs_stdfhtovp; 452116271Sphk if (vfsops->vfs_checkexp == NULL) 453116271Sphk /* check if file system is exported */ 454116271Sphk vfsops->vfs_checkexp = vfs_stdcheckexp; 455116271Sphk if (vfsops->vfs_vptofh == NULL) 456116271Sphk /* turn a vnode into an NFS file handle */ 457116271Sphk vfsops->vfs_vptofh = vfs_stdvptofh; 458116271Sphk if (vfsops->vfs_init == NULL) 459116271Sphk /* file system specific initialisation */ 460116271Sphk vfsops->vfs_init = vfs_stdinit; 461116271Sphk if (vfsops->vfs_uninit == NULL) 462116271Sphk /* file system specific uninitialisation */ 463116271Sphk vfsops->vfs_uninit = vfs_stduninit; 464116271Sphk if (vfsops->vfs_extattrctl == NULL) 465116271Sphk /* extended attribute control */ 466116271Sphk vfsops->vfs_extattrctl = vfs_stdextattrctl; 467116271Sphk 468116271Sphk /* 46940435Speter * Call init function for this VFS... 47040435Speter */ 47140435Speter (*(vfc->vfc_vfsops->vfs_init))(vfc); 47240435Speter 47340435Speter return 0; 4741541Srgrimes} 4752946Swollman 47640435Speter 47796755Strhodes/* Remove registration of a filesystem type */ 47840435Speterint 47941056Spetervfs_unregister(struct vfsconf *vfc) 48040435Speter{ 48140435Speter struct vfsconf *vfsp, *prev_vfsp; 48240435Speter int error, i, maxtypenum; 48340435Speter 48440435Speter i = vfc->vfc_typenum; 48540435Speter 48640435Speter prev_vfsp = NULL; 48740435Speter for (vfsp = vfsconf; vfsp; 48840435Speter prev_vfsp = vfsp, vfsp = vfsp->vfc_next) { 48940435Speter if (!strcmp(vfc->vfc_name, vfsp->vfc_name)) 49040435Speter break; 49140435Speter } 49240435Speter if (vfsp == NULL) 49340435Speter return EINVAL; 49440435Speter if (vfsp->vfc_refcount) 49540435Speter return EBUSY; 49640435Speter if (vfc->vfc_vfsops->vfs_uninit != NULL) { 49740435Speter error = (*vfc->vfc_vfsops->vfs_uninit)(vfsp); 49840435Speter if (error) 49940435Speter return (error); 50040435Speter } 50140435Speter if (prev_vfsp) 50240435Speter prev_vfsp->vfc_next = vfsp->vfc_next; 50340435Speter else 50440435Speter vfsconf = vfsp->vfc_next; 50540435Speter maxtypenum = VFS_GENERIC; 50640435Speter for (vfsp = vfsconf; vfsp != NULL; vfsp = vfsp->vfc_next) 50740435Speter if (maxtypenum < vfsp->vfc_typenum) 50840435Speter maxtypenum = vfsp->vfc_typenum; 50940435Speter maxvfsconf = maxtypenum + 1; 51040435Speter return 0; 51140435Speter} 51241056Speter 51391690Seivind/* 51496755Strhodes * Standard kernel module handling code for filesystem modules. 51591690Seivind * Referenced from VFS_SET(). 51691690Seivind */ 51741056Speterint 51841170Sbdevfs_modevent(module_t mod, int type, void *data) 51941056Speter{ 52041056Speter struct vfsconf *vfc; 52141056Speter int error = 0; 52241056Speter 52341056Speter vfc = (struct vfsconf *)data; 52441056Speter 52541056Speter switch (type) { 52641056Speter case MOD_LOAD: 52741056Speter if (vfc) 52841056Speter error = vfs_register(vfc); 52941056Speter break; 53041056Speter 53141056Speter case MOD_UNLOAD: 53241056Speter if (vfc) 53341056Speter error = vfs_unregister(vfc); 53441056Speter break; 53541056Speter default: /* including MOD_SHUTDOWN */ 53641056Speter break; 53741056Speter } 53841056Speter return (error); 53941056Speter} 540