vfs_init.c revision 12577
1139747Simp/* 24Srgrimes * Copyright (c) 1989, 1993 34Srgrimes * The Regents of the University of California. All rights reserved. 44Srgrimes * 58876Srgrimes * This code is derived from software contributed 64Srgrimes * to Berkeley by John Heidemann of the UCLA Ficus project. 74Srgrimes * 84Srgrimes * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 94Srgrimes * 104Srgrimes * Redistribution and use in source and binary forms, with or without 118876Srgrimes * modification, are permitted provided that the following conditions 128876Srgrimes * are met: 134Srgrimes * 1. Redistributions of source code must retain the above copyright 144Srgrimes * notice, this list of conditions and the following disclaimer. 158876Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 164Srgrimes * notice, this list of conditions and the following disclaimer in the 178876Srgrimes * documentation and/or other materials provided with the distribution. 184Srgrimes * 3. All advertising materials mentioning features or use of this software 194Srgrimes * must display the following acknowledgement: 204Srgrimes * This product includes software developed by the University of 214Srgrimes * California, Berkeley and its contributors. 228876Srgrimes * 4. Neither the name of the University nor the names of its contributors 234Srgrimes * may be used to endorse or promote products derived from this software 244Srgrimes * without specific prior written permission. 254Srgrimes * 264Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 274Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 284Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 294Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 304Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 314Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 324Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 334Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34116176Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35116176Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36116176Sobrien * SUCH DAMAGE. 37116176Sobrien * 382056Swollman * @(#)vfs_init.c 8.3 (Berkeley) 1/4/94 39131952Smarcel * $Id: vfs_init.c,v 1.15 1995/12/02 17:10:53 bde Exp $ 40145053Speter */ 4112734Sbde 42131952Smarcel 43131952Smarcel#include <sys/param.h> 44131952Smarcel#include <sys/systm.h> 4512662Sdg#include <sys/kernel.h> 4612734Sbde#include <sys/mount.h> 472056Swollman#include <sys/time.h> 484Srgrimes#include <sys/vnode.h> 494Srgrimes#include <sys/stat.h> 504Srgrimes#include <sys/namei.h> 514Srgrimes#include <sys/ucred.h> 524Srgrimes#include <sys/buf.h> 534Srgrimes#include <sys/errno.h> 544Srgrimes#include <sys/malloc.h> 55272958Spfg#include <sys/proc.h> 564Srgrimes#include <vm/vm.h> 57308418Skib#include <sys/sysctl.h> 584Srgrimes 59308418Skibextern void vfs_op_init __P((void)); 60283248Spfg 6112720Sphkstatic void vfsinit __P((void *)); 6212720SphkSYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL) 634Srgrimes 644Srgrimesvoid vfs_op_init __P((void)); 654Srgrimes 664Srgrimes/* 674Srgrimes * Sigh, such primitive tools are these... 68291407Szbb */ 69291407Szbb#if 0 70291407Szbb#define DODEBUG(A) A 71291407Szbb#else 72291407Szbb#define DODEBUG(A) 734Srgrimes#endif 74131952Smarcel 754Srgrimesstruct vfsconf void_vfsconf; 764Srgrimes 77131952Smarcelextern struct linker_set vfs_opv_descs_; 784Srgrimes#define vfs_opv_descs ((struct vnodeopv_desc **)vfs_opv_descs_.ls_items) 79291407Szbb 80291407Szbbextern struct linker_set vfs_set; 81291407Szbbstruct vfsops *vfssw[MOUNT_MAXTYPE + 1]; 82291407Szbbstruct vfsconf *vfsconf[MOUNT_MAXTYPE + 1]; 83137974Scognet 84291407Szbbextern struct vnodeop_desc *vfs_op_descs[]; 85291407Szbb /* and the operations they perform */ 86291407Szbb/* 87137974Scognet * This code doesn't work if the defn is **vnodop_defns with cc. 88291407Szbb * The problem is because of the compiler sometimes putting in an 89291407Szbb * extra level of indirection for arrays. It's an interesting 90291407Szbb * "feature" of C. 91137974Scognet */ 92283248Spfgint vfs_opv_numops; 93308418Skib 944Srgrimes/* 95283315Spfg * A miscellaneous routine. 96283315Spfg * A generic "default" routine that just returns an error. 974Srgrimes */ 98308418Skibint 99308418Skibvn_default_error() 100137974Scognet{ 101291407Szbb 102283088Spfg return (EOPNOTSUPP); 103137974Scognet} 104131952Smarcel 1054Srgrimes/* 1064Srgrimes * vfs_init.c 1074Srgrimes * 1084Srgrimes * Allocate and fill in operations vectors. 1094Srgrimes * 1104Srgrimes * An undocumented feature of this approach to defining operations is that 1114Srgrimes * there can be multiple entries in vfs_opv_descs for the same operations 1124Srgrimes * vector. This allows third parties to extend the set of operations 1134Srgrimes * supported by another layer in a binary compatibile way. For example, 1144Srgrimes * assume that NFS needed to be modified to support Ficus. NFS has an entry 115131952Smarcel * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 1164Srgrimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 1174Srgrimes * listing those new operations Ficus adds to NFS, all without modifying the 1184Srgrimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 1194Srgrimes * that is a(whole)nother story.) This is a feature. 1204Srgrimes */ 1214Srgrimesvoid 1224Srgrimesvfs_opv_init(struct vnodeopv_desc **them) 1234Srgrimes{ 1244Srgrimes int i, j, k; 1254Srgrimes vop_t ***opv_desc_vector_p; 126283088Spfg vop_t **opv_desc_vector; 127283088Spfg struct vnodeopv_entry_desc *opve_descp; 1284Srgrimes 129308418Skib /* 1304Srgrimes * Allocate the dynamic vectors and fill them in. 13183506Sdfr */ 13283506Sdfr for (i=0; them[i]; i++) { 13336735Sdfr opv_desc_vector_p = them[i]->opv_desc_vector_p; 1344Srgrimes /* 1358876Srgrimes * Allocate and init the vector, if it needs it. 136308418Skib * Also handle backwards compatibility. 1374Srgrimes */ 138308418Skib if (*opv_desc_vector_p == NULL) { 139308418Skib /* XXX - shouldn't be M_VNODE */ 140308418Skib MALLOC(*opv_desc_vector_p, vop_t **, 141308418Skib vfs_opv_numops * sizeof(vop_t *), M_VNODE, 142308418Skib M_WAITOK); 143308418Skib bzero(*opv_desc_vector_p, 144308418Skib vfs_opv_numops * sizeof(vop_t *)); 145308418Skib DODEBUG(printf("vector at %x allocated\n", 146308418Skib opv_desc_vector_p)); 147308418Skib } 148308418Skib opv_desc_vector = *opv_desc_vector_p; 149308418Skib for (j=0; them[i]->opv_desc_ops[j].opve_op; j++) { 150308418Skib opve_descp = &(them[i]->opv_desc_ops[j]); 151308418Skib 152308418Skib /* 153308418Skib * Sanity check: is this operation listed 154308418Skib * in the list of operations? We check this 155308418Skib * by seeing if its offest is zero. Since 156308418Skib * the default routine should always be listed 157308418Skib * first, it should be the only one with a zero 158308418Skib * offset. Any other operation with a zero 159308418Skib * offset is probably not listed in 160308418Skib * vfs_op_descs, and so is probably an error. 161308418Skib * 162308418Skib * A panic here means the layer programmer 1634Srgrimes * has committed the all-too common bug 1644Srgrimes * of adding a new operation to the layer's 165283088Spfg * list of vnode operations but 1664Srgrimes * not adding the operation to the system-wide 1674Srgrimes * list of supported operations. 168283088Spfg */ 1694Srgrimes if (opve_descp->opve_op->vdesc_offset == 0 && 1704Srgrimes opve_descp->opve_op->vdesc_offset != 1714Srgrimes VOFFSET(vop_default)) { 1724Srgrimes printf("operation %s not listed in %s.\n", 1734Srgrimes opve_descp->opve_op->vdesc_name, 1744Srgrimes "vfs_op_descs"); 1754Srgrimes panic ("vfs_opv_init: bad operation"); 1764Srgrimes } 177283088Spfg /* 1784Srgrimes * Fill in this entry. 1794Srgrimes */ 1804Srgrimes opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 1814Srgrimes opve_descp->opve_impl; 18298694Smux } 1834Srgrimes } 184283088Spfg /* 1854Srgrimes * Finally, go back and replace unfilled routines 1864Srgrimes * with their default. (Sigh, an O(n^3) algorithm. I 1874Srgrimes * could make it better, but that'd be work, and n is small.) 1884Srgrimes */ 189283315Spfg for (i = 0; them[i]; i++) { 1904Srgrimes opv_desc_vector = *(them[i]->opv_desc_vector_p); 1914Srgrimes /* 1924Srgrimes * Force every operations vector to have a default routine. 1934Srgrimes */ 1944Srgrimes if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { 1954Srgrimes panic("vfs_opv_init: operation vector without default routine."); 1964Srgrimes } 1974Srgrimes for (k = 0; k<vfs_opv_numops; k++) 1984Srgrimes if (opv_desc_vector[k] == NULL) 1994Srgrimes opv_desc_vector[k] = 200283088Spfg opv_desc_vector[VOFFSET(vop_default)]; 2014Srgrimes } 2024Srgrimes} 2034Srgrimes 2044Srgrimes/* 20598694Smux * Initialize known vnode operations vectors. 2064Srgrimes */ 207283088Spfgvoid 2084Srgrimesvfs_op_init() 2094Srgrimes{ 2104Srgrimes int i; 211283088Spfg 2124Srgrimes DODEBUG(printf("Vnode_interface_init.\n")); 2134Srgrimes /* 214283088Spfg * Set all vnode vectors to a well known value. 2154Srgrimes */ 2164Srgrimes for (i = 0; vfs_opv_descs[i]; i++) 2174Srgrimes *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL; 218283248Spfg /* 2194Srgrimes * Figure out how many ops there are by counting the table, 220283315Spfg * and assign each its offset. 2214Srgrimes */ 2224Srgrimes for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) { 223308418Skib vfs_op_descs[i]->vdesc_offset = vfs_opv_numops; 2244Srgrimes vfs_opv_numops++; 2254Srgrimes } 2264Srgrimes DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops)); 2274Srgrimes} 2284Srgrimes 2294Srgrimes/* 230269982Simp * Routines having to do with the management of the vnode table. 231269982Simp */ 232269982Simpextern struct vnodeops dead_vnodeops; 233283088Spfgextern struct vnodeops spec_vnodeops; 2344Srgrimesstruct vattr va_null; 2354Srgrimes 2364Srgrimes/* 2374Srgrimes * Initialize the vnode structures and initialize each file system type. 2384Srgrimes */ 2394Srgrimes/* ARGSUSED*/ 2404Srgrimesstatic void 241283088Spfgvfsinit(dummy) 2424Srgrimes void *dummy; 2434Srgrimes{ 2444Srgrimes struct vfsops **vfsp; 2454Srgrimes struct vfsconf **vfc; 24681670Sobrien int i; 2474Srgrimes 2484Srgrimes /* 2494Srgrimes * Initialize the VFS switch table 2504Srgrimes */ 2514Srgrimes for(i = 0; i < MOUNT_MAXTYPE + 1; i++) { 2524Srgrimes vfsconf[i] = &void_vfsconf; 2534Srgrimes } 2544Srgrimes 255131952Smarcel vfc = (struct vfsconf **)vfs_set.ls_items; 2564Srgrimes while(*vfc) { 2574Srgrimes vfssw[(**vfc).vfc_index] = (**vfc).vfc_vfsops; 2584Srgrimes vfsconf[(**vfc).vfc_index] = *vfc; 2594Srgrimes vfc++; 2604Srgrimes } 261131952Smarcel 2624Srgrimes /* 2634Srgrimes * Initialize the vnode table 2644Srgrimes */ 2654Srgrimes vntblinit(); 2664Srgrimes /* 2674Srgrimes * Initialize the vnode name cache 2684Srgrimes */ 2694Srgrimes nchinit(); 2704Srgrimes /* 2714Srgrimes * Build vnode operation vectors. 2724Srgrimes */ 2734Srgrimes vfs_op_init(); 274283248Spfg vfs_opv_init(vfs_opv_descs); /* finish the job */ 2754Srgrimes /* 2764Srgrimes * Initialize each file system type. 2774Srgrimes */ 2784Srgrimes vattr_null(&va_null); 2794Srgrimes for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) { 2804Srgrimes if (*vfsp == NULL) 2814Srgrimes continue; 2828876Srgrimes (*(*vfsp)->vfs_init)(); 2834Srgrimes } 2844Srgrimes} 2854Srgrimes 2864Srgrimes/* 2874Srgrimes * kernel related system variables. 2884Srgrimes */ 2894Srgrimes 2904Srgrimesstatic int 2914Srgrimessysctl_fs_vfsconf SYSCTL_HANDLER_ARGS 2924Srgrimes{ 2934Srgrimes int i, error; 2948876Srgrimes 2954Srgrimes if (req->newptr) 2964Srgrimes return EINVAL; 297131952Smarcel for(i = 0; i < MOUNT_MAXTYPE + 1; i++) { 2984Srgrimes error = SYSCTL_OUT(req, vfsconf[i], sizeof *vfsconf[i]); 299131952Smarcel if(error) 300131952Smarcel return error; 3014Srgrimes } 3024Srgrimes return (error); 3034Srgrimes 3044Srgrimes} 3054Srgrimes 306283088SpfgSYSCTL_PROC(_fs, FS_VFSCONF, vfsconf, CTLTYPE_OPAQUE|CTLFLAG_RD, 307181175Scognet 0, 0, sysctl_fs_vfsconf, ""); 308131952Smarcel 309131952Smarcel/* 310131952Smarcel * This goop is here to support a loadable NFS module... grumble... 311131952Smarcel */ 312131952Smarcelvoid (*lease_check) __P((struct vnode *, struct proc *, struct ucred *, int)) 3134Srgrimes = 0; 314131952Smarcelvoid (*lease_updatetime) __P((int)) 3154Srgrimes = 0; 3164Srgrimes 3174Srgrimes