vfs_init.c revision 2946
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 392946Swollman * $Id: vfs_init.c,v 1.4 1994/08/18 22:35:08 wollman Exp $ 401541Srgrimes */ 411541Srgrimes 421541Srgrimes 431541Srgrimes#include <sys/param.h> 442112Swollman#include <sys/systm.h> 452946Swollman#include <sys/kernel.h> 461541Srgrimes#include <sys/mount.h> 471541Srgrimes#include <sys/time.h> 481541Srgrimes#include <sys/vnode.h> 491541Srgrimes#include <sys/stat.h> 501541Srgrimes#include <sys/namei.h> 511541Srgrimes#include <sys/ucred.h> 521541Srgrimes#include <sys/buf.h> 531541Srgrimes#include <sys/errno.h> 541541Srgrimes#include <sys/malloc.h> 552946Swollman#include <sys/proc.h> 562946Swollman#include <vm/vm.h> 572946Swollman#include <sys/sysctl.h> 581541Srgrimes 591541Srgrimes/* 601541Srgrimes * Sigh, such primitive tools are these... 611541Srgrimes */ 621541Srgrimes#if 0 631541Srgrimes#define DODEBUG(A) A 641541Srgrimes#else 651541Srgrimes#define DODEBUG(A) 661541Srgrimes#endif 671541Srgrimes 682946Swollmanstruct vfsconf void_vfsconf; 692946Swollman 702946Swollmanextern struct linker_set vfs_opv_descs_; 712946Swollman#define vfs_opv_descs ((struct vnodeopv_desc **)vfs_opv_descs_.ls_items) 722946Swollman 732946Swollmanextern struct linker_set vfs_set; 742946Swollmanstruct vfsops *vfssw[MOUNT_MAXTYPE + 1]; 752946Swollmanstruct vfsconf *vfsconf[MOUNT_MAXTYPE + 1]; 762946Swollman 771541Srgrimesextern struct vnodeop_desc *vfs_op_descs[]; 781541Srgrimes /* and the operations they perform */ 791541Srgrimes/* 801541Srgrimes * This code doesn't work if the defn is **vnodop_defns with cc. 811541Srgrimes * The problem is because of the compiler sometimes putting in an 821541Srgrimes * extra level of indirection for arrays. It's an interesting 831541Srgrimes * "feature" of C. 841541Srgrimes */ 851541Srgrimesint vfs_opv_numops; 861541Srgrimes 872946Swollmantypedef int (*PFI)(); /* the standard Pointer to a Function returning an Int */ 881541Srgrimes 891541Srgrimes/* 901541Srgrimes * A miscellaneous routine. 911541Srgrimes * A generic "default" routine that just returns an error. 921541Srgrimes */ 931541Srgrimesint 941541Srgrimesvn_default_error() 951541Srgrimes{ 961541Srgrimes 971541Srgrimes return (EOPNOTSUPP); 981541Srgrimes} 991541Srgrimes 1001541Srgrimes/* 1011541Srgrimes * vfs_init.c 1021541Srgrimes * 1031541Srgrimes * Allocate and fill in operations vectors. 1041541Srgrimes * 1051541Srgrimes * An undocumented feature of this approach to defining operations is that 1061541Srgrimes * there can be multiple entries in vfs_opv_descs for the same operations 1071541Srgrimes * vector. This allows third parties to extend the set of operations 1081541Srgrimes * supported by another layer in a binary compatibile way. For example, 1091541Srgrimes * assume that NFS needed to be modified to support Ficus. NFS has an entry 1101541Srgrimes * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 1111541Srgrimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 1121541Srgrimes * listing those new operations Ficus adds to NFS, all without modifying the 1131541Srgrimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 1141541Srgrimes * that is a(whole)nother story.) This is a feature. 1151541Srgrimes */ 1161541Srgrimesvoid 1172946Swollmanvfs_opv_init(struct vnodeopv_desc **them) 1181541Srgrimes{ 1191541Srgrimes int i, j, k; 1201541Srgrimes int (***opv_desc_vector_p)(); 1211541Srgrimes int (**opv_desc_vector)(); 1221541Srgrimes struct vnodeopv_entry_desc *opve_descp; 1231541Srgrimes 1241541Srgrimes /* 1251541Srgrimes * Allocate the dynamic vectors and fill them in. 1261541Srgrimes */ 1272946Swollman for (i=0; them[i]; i++) { 1282946Swollman opv_desc_vector_p = them[i]->opv_desc_vector_p; 1291541Srgrimes /* 1301541Srgrimes * Allocate and init the vector, if it needs it. 1311541Srgrimes * Also handle backwards compatibility. 1321541Srgrimes */ 1331541Srgrimes if (*opv_desc_vector_p == NULL) { 1341541Srgrimes /* XXX - shouldn't be M_VNODE */ 1351541Srgrimes MALLOC(*opv_desc_vector_p, PFI*, 1361541Srgrimes vfs_opv_numops*sizeof(PFI), M_VNODE, M_WAITOK); 1371541Srgrimes bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI)); 1381541Srgrimes DODEBUG(printf("vector at %x allocated\n", 1391541Srgrimes opv_desc_vector_p)); 1401541Srgrimes } 1411541Srgrimes opv_desc_vector = *opv_desc_vector_p; 1422946Swollman for (j=0; them[i]->opv_desc_ops[j].opve_op; j++) { 1432946Swollman opve_descp = &(them[i]->opv_desc_ops[j]); 1441541Srgrimes 1451541Srgrimes /* 1461541Srgrimes * Sanity check: is this operation listed 1471541Srgrimes * in the list of operations? We check this 1481541Srgrimes * by seeing if its offest is zero. Since 1491541Srgrimes * the default routine should always be listed 1501541Srgrimes * first, it should be the only one with a zero 1511541Srgrimes * offset. Any other operation with a zero 1521541Srgrimes * offset is probably not listed in 1531541Srgrimes * vfs_op_descs, and so is probably an error. 1541541Srgrimes * 1551541Srgrimes * A panic here means the layer programmer 1561541Srgrimes * has committed the all-too common bug 1571541Srgrimes * of adding a new operation to the layer's 1581541Srgrimes * list of vnode operations but 1591541Srgrimes * not adding the operation to the system-wide 1601541Srgrimes * list of supported operations. 1611541Srgrimes */ 1621541Srgrimes if (opve_descp->opve_op->vdesc_offset == 0 && 1631541Srgrimes opve_descp->opve_op->vdesc_offset != 1641541Srgrimes VOFFSET(vop_default)) { 1651541Srgrimes printf("operation %s not listed in %s.\n", 1661541Srgrimes opve_descp->opve_op->vdesc_name, 1671541Srgrimes "vfs_op_descs"); 1681541Srgrimes panic ("vfs_opv_init: bad operation"); 1691541Srgrimes } 1701541Srgrimes /* 1711541Srgrimes * Fill in this entry. 1721541Srgrimes */ 1731541Srgrimes opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 1741541Srgrimes opve_descp->opve_impl; 1751541Srgrimes } 1761541Srgrimes } 1771541Srgrimes /* 1781541Srgrimes * Finally, go back and replace unfilled routines 1791541Srgrimes * with their default. (Sigh, an O(n^3) algorithm. I 1801541Srgrimes * could make it better, but that'd be work, and n is small.) 1811541Srgrimes */ 1822946Swollman for (i = 0; them[i]; i++) { 1832946Swollman opv_desc_vector = *(them[i]->opv_desc_vector_p); 1841541Srgrimes /* 1851541Srgrimes * Force every operations vector to have a default routine. 1861541Srgrimes */ 1871541Srgrimes if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { 1881541Srgrimes panic("vfs_opv_init: operation vector without default routine."); 1891541Srgrimes } 1901541Srgrimes for (k = 0; k<vfs_opv_numops; k++) 1911541Srgrimes if (opv_desc_vector[k] == NULL) 1921541Srgrimes opv_desc_vector[k] = 1931541Srgrimes opv_desc_vector[VOFFSET(vop_default)]; 1941541Srgrimes } 1951541Srgrimes} 1961541Srgrimes 1971541Srgrimes/* 1981541Srgrimes * Initialize known vnode operations vectors. 1991541Srgrimes */ 2001541Srgrimesvoid 2011541Srgrimesvfs_op_init() 2021541Srgrimes{ 2031541Srgrimes int i; 2041541Srgrimes 2051541Srgrimes DODEBUG(printf("Vnode_interface_init.\n")); 2061541Srgrimes /* 2071541Srgrimes * Set all vnode vectors to a well known value. 2081541Srgrimes */ 2091541Srgrimes for (i = 0; vfs_opv_descs[i]; i++) 2101541Srgrimes *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL; 2111541Srgrimes /* 2121541Srgrimes * Figure out how many ops there are by counting the table, 2131541Srgrimes * and assign each its offset. 2141541Srgrimes */ 2151541Srgrimes for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) { 2161541Srgrimes vfs_op_descs[i]->vdesc_offset = vfs_opv_numops; 2171541Srgrimes vfs_opv_numops++; 2181541Srgrimes } 2191541Srgrimes DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops)); 2201541Srgrimes} 2211541Srgrimes 2221541Srgrimes/* 2231541Srgrimes * Routines having to do with the management of the vnode table. 2241541Srgrimes */ 2251541Srgrimesextern struct vnodeops dead_vnodeops; 2261541Srgrimesextern struct vnodeops spec_vnodeops; 2271541Srgrimesextern void vclean(); 2281541Srgrimesstruct vattr va_null; 2291541Srgrimes 2301541Srgrimes/* 2311541Srgrimes * Initialize the vnode structures and initialize each file system type. 2321541Srgrimes */ 2331549Srgrimesvoid 2341541Srgrimesvfsinit() 2351541Srgrimes{ 2361541Srgrimes struct vfsops **vfsp; 2372946Swollman struct vfsconf **vfc; 2382946Swollman int i; 2391541Srgrimes 2401541Srgrimes /* 2412946Swollman * Initialize the VFS switch table 2422946Swollman */ 2432946Swollman for(i = 0; i < MOUNT_MAXTYPE + 1; i++) { 2442946Swollman vfsconf[i] = &void_vfsconf; 2452946Swollman } 2462946Swollman 2472946Swollman vfc = (struct vfsconf **)vfs_set.ls_items; 2482946Swollman while(*vfc) { 2492946Swollman vfssw[(**vfc).vfc_index] = (**vfc).vfc_vfsops; 2502946Swollman vfsconf[(**vfc).vfc_index] = *vfc; 2512946Swollman vfc++; 2522946Swollman } 2532946Swollman 2542946Swollman /* 2551541Srgrimes * Initialize the vnode table 2561541Srgrimes */ 2571541Srgrimes vntblinit(); 2581541Srgrimes /* 2591541Srgrimes * Initialize the vnode name cache 2601541Srgrimes */ 2611541Srgrimes nchinit(); 2621541Srgrimes /* 2631541Srgrimes * Build vnode operation vectors. 2641541Srgrimes */ 2651541Srgrimes vfs_op_init(); 2662946Swollman vfs_opv_init(vfs_opv_descs); /* finish the job */ 2671541Srgrimes /* 2681541Srgrimes * Initialize each file system type. 2691541Srgrimes */ 2701541Srgrimes vattr_null(&va_null); 2711541Srgrimes for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) { 2721541Srgrimes if (*vfsp == NULL) 2731541Srgrimes continue; 2741541Srgrimes (*(*vfsp)->vfs_init)(); 2751541Srgrimes } 2761541Srgrimes} 2772946Swollman 2782946Swollman/* 2792946Swollman * kernel related system variables. 2802946Swollman */ 2812946Swollmanint 2822946Swollmanfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 2832946Swollman int *name; 2842946Swollman u_int namelen; 2852946Swollman void *oldp; 2862946Swollman size_t *oldlenp; 2872946Swollman void *newp; 2882946Swollman size_t newlen; 2892946Swollman struct proc *p; 2902946Swollman{ 2912946Swollman int i; 2922946Swollman int error; 2932946Swollman int buflen = *oldlenp; 2942946Swollman caddr_t where = newp, start = newp; 2952946Swollman 2962946Swollman switch (name[0]) { 2972946Swollman case FS_VFSCONF: 2982946Swollman if (namelen != 1) return ENOTDIR; 2992946Swollman 3002946Swollman if (oldp == NULL) { 3012946Swollman *oldlenp = (MOUNT_MAXTYPE+1) * sizeof(struct vfsconf); 3022946Swollman return 0; 3032946Swollman } 3042946Swollman if (newp) { 3052946Swollman return EINVAL; 3062946Swollman } 3072946Swollman 3082946Swollman for(i = 0; i < MOUNT_MAXTYPE + 1; i++) { 3092946Swollman if(buflen < sizeof *vfsconf[i]) { 3102946Swollman *oldlenp = where - start; 3112946Swollman return ENOMEM; 3122946Swollman } 3132946Swollman 3142946Swollman if(error = copyout(vfsconf[i], where, 3152946Swollman sizeof *vfsconf[i])) 3162946Swollman return error; 3172946Swollman where += sizeof *vfsconf[i]; 3182946Swollman buflen -= sizeof *vfsconf[i]; 3192946Swollman } 3202946Swollman *oldlenp = where - start; 3212946Swollman return 0; 3222946Swollman 3232946Swollman default: 3242946Swollman return (EOPNOTSUPP); 3252946Swollman } 3262946Swollman /* NOTREACHED */ 3272946Swollman} 3282946Swollman 329