1df8bae1dSRodney W. Grimes /* 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 * 3. All advertising materials mentioning features or use of this software 19df8bae1dSRodney W. Grimes * must display the following acknowledgement: 20df8bae1dSRodney W. Grimes * This product includes software developed by the University of 21df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 22df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 23df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 24df8bae1dSRodney W. Grimes * without specific prior written permission. 25df8bae1dSRodney W. Grimes * 26df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36df8bae1dSRodney W. Grimes * SUCH DAMAGE. 37df8bae1dSRodney W. Grimes * 38df8bae1dSRodney W. Grimes * @(#)vfs_init.c 8.3 (Berkeley) 1/4/94 39a1c995b6SPoul-Henning Kamp * $Id: vfs_init.c,v 1.28 1997/09/21 04:22:59 dyson Exp $ 40df8bae1dSRodney W. Grimes */ 41df8bae1dSRodney W. Grimes 42df8bae1dSRodney W. Grimes 43df8bae1dSRodney W. Grimes #include <sys/param.h> 44f23b4c91SGarrett Wollman #include <sys/systm.h> 45c901836cSGarrett Wollman #include <sys/kernel.h> 46df8bae1dSRodney W. Grimes #include <sys/mount.h> 47df8bae1dSRodney W. Grimes #include <sys/vnode.h> 48df8bae1dSRodney W. Grimes #include <sys/malloc.h> 4999448ed1SJohn Dyson #include <vm/vm_zone.h> 50df8bae1dSRodney W. Grimes 5127a0b398SPoul-Henning Kamp static void vfs_op_init __P((void)); 5298d93822SBruce Evans 534590fd3aSDavid Greenman static void vfsinit __P((void *)); 542b14f991SJulian Elischer SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_FIRST, vfsinit, NULL) 552b14f991SJulian Elischer 56a1c995b6SPoul-Henning Kamp MALLOC_DEFINE(M_VNODE, "vnodes", "Dynamically allocated vnodes"); 57a1c995b6SPoul-Henning Kamp 582b14f991SJulian Elischer /* 59df8bae1dSRodney W. Grimes * Sigh, such primitive tools are these... 60df8bae1dSRodney W. Grimes */ 61df8bae1dSRodney W. Grimes #if 0 62df8bae1dSRodney W. Grimes #define DODEBUG(A) A 63df8bae1dSRodney W. Grimes #else 64df8bae1dSRodney W. Grimes #define DODEBUG(A) 65df8bae1dSRodney W. Grimes #endif 66df8bae1dSRodney W. Grimes 67c901836cSGarrett Wollman struct vfsconf void_vfsconf; 68c901836cSGarrett Wollman 69c901836cSGarrett Wollman extern struct linker_set vfs_opv_descs_; 70c901836cSGarrett Wollman #define vfs_opv_descs ((struct vnodeopv_desc **)vfs_opv_descs_.ls_items) 71c901836cSGarrett Wollman 72c901836cSGarrett Wollman extern struct linker_set vfs_set; 73c901836cSGarrett Wollman 74df8bae1dSRodney W. Grimes extern struct vnodeop_desc *vfs_op_descs[]; 75df8bae1dSRodney W. Grimes /* and the operations they perform */ 76df8bae1dSRodney W. Grimes 77df8bae1dSRodney W. Grimes /* 7899448ed1SJohn Dyson * Zone for namei 7999448ed1SJohn Dyson */ 8099448ed1SJohn Dyson struct vm_zone *namei_zone; 8199448ed1SJohn Dyson 8299448ed1SJohn Dyson /* 83df8bae1dSRodney W. Grimes * A miscellaneous routine. 84df8bae1dSRodney W. Grimes * A generic "default" routine that just returns an error. 85df8bae1dSRodney W. Grimes */ 86df8bae1dSRodney W. Grimes int 87df8bae1dSRodney W. Grimes vn_default_error() 88df8bae1dSRodney W. Grimes { 89df8bae1dSRodney W. Grimes 90df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 91df8bae1dSRodney W. Grimes } 92df8bae1dSRodney W. Grimes 93df8bae1dSRodney W. Grimes /* 94df8bae1dSRodney W. Grimes * vfs_init.c 95df8bae1dSRodney W. Grimes * 96df8bae1dSRodney W. Grimes * Allocate and fill in operations vectors. 97df8bae1dSRodney W. Grimes * 98df8bae1dSRodney W. Grimes * An undocumented feature of this approach to defining operations is that 99df8bae1dSRodney W. Grimes * there can be multiple entries in vfs_opv_descs for the same operations 100df8bae1dSRodney W. Grimes * vector. This allows third parties to extend the set of operations 101df8bae1dSRodney W. Grimes * supported by another layer in a binary compatibile way. For example, 102df8bae1dSRodney W. Grimes * assume that NFS needed to be modified to support Ficus. NFS has an entry 103df8bae1dSRodney W. Grimes * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 104df8bae1dSRodney W. Grimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 105df8bae1dSRodney W. Grimes * listing those new operations Ficus adds to NFS, all without modifying the 106df8bae1dSRodney W. Grimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 107df8bae1dSRodney W. Grimes * that is a(whole)nother story.) This is a feature. 108bf1d104aSPoul-Henning Kamp * 109bf1d104aSPoul-Henning Kamp * Without an explicit reserve area, however, you must replace vnode_if.c 110bf1d104aSPoul-Henning Kamp * and vnode_if.h when you do this, or you will be derefrencing of the 111bf1d104aSPoul-Henning Kamp * end of vfs_op_descs[]. This is a flaw in the use of a structure 112bf1d104aSPoul-Henning Kamp * pointer array rather than an agregate to define vfs_op_descs. So 113bf1d104aSPoul-Henning Kamp * it's not a very dynamic "feature". 114df8bae1dSRodney W. Grimes */ 115df8bae1dSRodney W. Grimes void 116c901836cSGarrett Wollman vfs_opv_init(struct vnodeopv_desc **them) 117df8bae1dSRodney W. Grimes { 118df8bae1dSRodney W. Grimes int i, j, k; 119f57e6547SBruce Evans vop_t ***opv_desc_vector_p; 120f57e6547SBruce Evans vop_t **opv_desc_vector; 121df8bae1dSRodney W. Grimes struct vnodeopv_entry_desc *opve_descp; 122df8bae1dSRodney W. Grimes 123df8bae1dSRodney W. Grimes /* 124df8bae1dSRodney W. Grimes * Allocate the dynamic vectors and fill them in. 125df8bae1dSRodney W. Grimes */ 126c901836cSGarrett Wollman for (i=0; them[i]; i++) { 127c901836cSGarrett Wollman opv_desc_vector_p = them[i]->opv_desc_vector_p; 128df8bae1dSRodney W. Grimes /* 129df8bae1dSRodney W. Grimes * Allocate and init the vector, if it needs it. 130df8bae1dSRodney W. Grimes * Also handle backwards compatibility. 131df8bae1dSRodney W. Grimes */ 132df8bae1dSRodney W. Grimes if (*opv_desc_vector_p == NULL) { 133df8bae1dSRodney W. Grimes /* XXX - shouldn't be M_VNODE */ 134f57e6547SBruce Evans MALLOC(*opv_desc_vector_p, vop_t **, 135f57e6547SBruce Evans vfs_opv_numops * sizeof(vop_t *), M_VNODE, 136f57e6547SBruce Evans M_WAITOK); 137f57e6547SBruce Evans bzero(*opv_desc_vector_p, 138f57e6547SBruce Evans vfs_opv_numops * sizeof(vop_t *)); 139df8bae1dSRodney W. Grimes DODEBUG(printf("vector at %x allocated\n", 140df8bae1dSRodney W. Grimes opv_desc_vector_p)); 141df8bae1dSRodney W. Grimes } 142df8bae1dSRodney W. Grimes opv_desc_vector = *opv_desc_vector_p; 143c901836cSGarrett Wollman for (j=0; them[i]->opv_desc_ops[j].opve_op; j++) { 144c901836cSGarrett Wollman opve_descp = &(them[i]->opv_desc_ops[j]); 145df8bae1dSRodney W. Grimes 146df8bae1dSRodney W. Grimes /* 147df8bae1dSRodney W. Grimes * Sanity check: is this operation listed 148df8bae1dSRodney W. Grimes * in the list of operations? We check this 149df8bae1dSRodney W. Grimes * by seeing if its offest is zero. Since 150df8bae1dSRodney W. Grimes * the default routine should always be listed 151df8bae1dSRodney W. Grimes * first, it should be the only one with a zero 152df8bae1dSRodney W. Grimes * offset. Any other operation with a zero 153df8bae1dSRodney W. Grimes * offset is probably not listed in 154df8bae1dSRodney W. Grimes * vfs_op_descs, and so is probably an error. 155df8bae1dSRodney W. Grimes * 156df8bae1dSRodney W. Grimes * A panic here means the layer programmer 157df8bae1dSRodney W. Grimes * has committed the all-too common bug 158df8bae1dSRodney W. Grimes * of adding a new operation to the layer's 159df8bae1dSRodney W. Grimes * list of vnode operations but 160df8bae1dSRodney W. Grimes * not adding the operation to the system-wide 161df8bae1dSRodney W. Grimes * list of supported operations. 162df8bae1dSRodney W. Grimes */ 163df8bae1dSRodney W. Grimes if (opve_descp->opve_op->vdesc_offset == 0 && 164df8bae1dSRodney W. Grimes opve_descp->opve_op->vdesc_offset != 165df8bae1dSRodney W. Grimes VOFFSET(vop_default)) { 166df8bae1dSRodney W. Grimes printf("operation %s not listed in %s.\n", 167df8bae1dSRodney W. Grimes opve_descp->opve_op->vdesc_name, 168df8bae1dSRodney W. Grimes "vfs_op_descs"); 169df8bae1dSRodney W. Grimes panic ("vfs_opv_init: bad operation"); 170df8bae1dSRodney W. Grimes } 171df8bae1dSRodney W. Grimes /* 172df8bae1dSRodney W. Grimes * Fill in this entry. 173df8bae1dSRodney W. Grimes */ 174df8bae1dSRodney W. Grimes opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 175df8bae1dSRodney W. Grimes opve_descp->opve_impl; 176df8bae1dSRodney W. Grimes } 177df8bae1dSRodney W. Grimes } 178df8bae1dSRodney W. Grimes /* 179df8bae1dSRodney W. Grimes * Finally, go back and replace unfilled routines 180df8bae1dSRodney W. Grimes * with their default. (Sigh, an O(n^3) algorithm. I 181df8bae1dSRodney W. Grimes * could make it better, but that'd be work, and n is small.) 182df8bae1dSRodney W. Grimes */ 183c901836cSGarrett Wollman for (i = 0; them[i]; i++) { 184c901836cSGarrett Wollman opv_desc_vector = *(them[i]->opv_desc_vector_p); 185df8bae1dSRodney W. Grimes /* 186df8bae1dSRodney W. Grimes * Force every operations vector to have a default routine. 187df8bae1dSRodney W. Grimes */ 188df8bae1dSRodney W. Grimes if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { 189df8bae1dSRodney W. Grimes panic("vfs_opv_init: operation vector without default routine."); 190df8bae1dSRodney W. Grimes } 191df8bae1dSRodney W. Grimes for (k = 0; k<vfs_opv_numops; k++) 192df8bae1dSRodney W. Grimes if (opv_desc_vector[k] == NULL) 193df8bae1dSRodney W. Grimes opv_desc_vector[k] = 194df8bae1dSRodney W. Grimes opv_desc_vector[VOFFSET(vop_default)]; 195df8bae1dSRodney W. Grimes } 196df8bae1dSRodney W. Grimes } 197df8bae1dSRodney W. Grimes 198df8bae1dSRodney W. Grimes /* 199df8bae1dSRodney W. Grimes * Initialize known vnode operations vectors. 200df8bae1dSRodney W. Grimes */ 20127a0b398SPoul-Henning Kamp static void 202df8bae1dSRodney W. Grimes vfs_op_init() 203df8bae1dSRodney W. Grimes { 204df8bae1dSRodney W. Grimes int i; 205df8bae1dSRodney W. Grimes 206df8bae1dSRodney W. Grimes DODEBUG(printf("Vnode_interface_init.\n")); 207bf1d104aSPoul-Henning Kamp DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops)); 208df8bae1dSRodney W. Grimes /* 209df8bae1dSRodney W. Grimes * Set all vnode vectors to a well known value. 210df8bae1dSRodney W. Grimes */ 211df8bae1dSRodney W. Grimes for (i = 0; vfs_opv_descs[i]; i++) 212df8bae1dSRodney W. Grimes *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL; 213df8bae1dSRodney W. Grimes /* 214bf1d104aSPoul-Henning Kamp * assign each op to its offset 215bf1d104aSPoul-Henning Kamp * 216bf1d104aSPoul-Henning Kamp * XXX This should not be needed, but is because the per 217bf1d104aSPoul-Henning Kamp * XXX FS ops tables are not sorted according to the 218bf1d104aSPoul-Henning Kamp * XXX vnodeop_desc's offset in vfs_op_descs. This 219bf1d104aSPoul-Henning Kamp * XXX is the same reason we have to take the hit for 220bf1d104aSPoul-Henning Kamp * XXX the static inline function calls instead of using 221bf1d104aSPoul-Henning Kamp * XXX simple macro references. 222df8bae1dSRodney W. Grimes */ 223bf1d104aSPoul-Henning Kamp for (i = 0; i < vfs_opv_numops; i++) 224bf1d104aSPoul-Henning Kamp vfs_op_descs[i]->vdesc_offset = i; 225df8bae1dSRodney W. Grimes } 226df8bae1dSRodney W. Grimes 227df8bae1dSRodney W. Grimes /* 228df8bae1dSRodney W. Grimes * Routines having to do with the management of the vnode table. 229df8bae1dSRodney W. Grimes */ 230df8bae1dSRodney W. Grimes extern struct vnodeops dead_vnodeops; 231df8bae1dSRodney W. Grimes extern struct vnodeops spec_vnodeops; 232df8bae1dSRodney W. Grimes struct vattr va_null; 233df8bae1dSRodney W. Grimes 234df8bae1dSRodney W. Grimes /* 235df8bae1dSRodney W. Grimes * Initialize the vnode structures and initialize each file system type. 236df8bae1dSRodney W. Grimes */ 2372b14f991SJulian Elischer /* ARGSUSED*/ 2382b14f991SJulian Elischer static void 239d841aaa7SBruce Evans vfsinit(dummy) 240d841aaa7SBruce Evans void *dummy; 241df8bae1dSRodney W. Grimes { 242c901836cSGarrett Wollman struct vfsconf **vfc; 243996c772fSJohn Dyson int maxtypenum; 244df8bae1dSRodney W. Grimes 24599448ed1SJohn Dyson namei_zone = zinit("NAMEI", MAXPATHLEN, 0, 0, 2); 24699448ed1SJohn Dyson 247df8bae1dSRodney W. Grimes /* 248df8bae1dSRodney W. Grimes * Initialize the vnode table 249df8bae1dSRodney W. Grimes */ 250df8bae1dSRodney W. Grimes vntblinit(); 251df8bae1dSRodney W. Grimes /* 252df8bae1dSRodney W. Grimes * Initialize the vnode name cache 253df8bae1dSRodney W. Grimes */ 254df8bae1dSRodney W. Grimes nchinit(); 255df8bae1dSRodney W. Grimes /* 256df8bae1dSRodney W. Grimes * Build vnode operation vectors. 257df8bae1dSRodney W. Grimes */ 258df8bae1dSRodney W. Grimes vfs_op_init(); 259c901836cSGarrett Wollman vfs_opv_init(vfs_opv_descs); /* finish the job */ 260df8bae1dSRodney W. Grimes /* 261df8bae1dSRodney W. Grimes * Initialize each file system type. 262df8bae1dSRodney W. Grimes */ 263df8bae1dSRodney W. Grimes vattr_null(&va_null); 264996c772fSJohn Dyson maxtypenum = 0; 265996c772fSJohn Dyson vfc = (struct vfsconf **)vfs_set.ls_items; 266996c772fSJohn Dyson vfsconf = *vfc; /* simulate Lite2 vfsconf array */ 267996c772fSJohn Dyson while (*vfc) { 268996c772fSJohn Dyson struct vfsconf *vfsp = *vfc; 269996c772fSJohn Dyson 270996c772fSJohn Dyson vfc++; 271996c772fSJohn Dyson vfsp->vfc_next = *vfc; 272996c772fSJohn Dyson if (maxtypenum <= vfsp->vfc_typenum) 273996c772fSJohn Dyson maxtypenum = vfsp->vfc_typenum + 1; 274996c772fSJohn Dyson (*vfsp->vfc_vfsops->vfs_init)(vfsp); 275df8bae1dSRodney W. Grimes } 276996c772fSJohn Dyson /* next vfc_typenum to be used */ 277996c772fSJohn Dyson maxvfsconf = maxtypenum; 278df8bae1dSRodney W. Grimes } 279c901836cSGarrett Wollman 280c901836cSGarrett Wollman /* 281c901836cSGarrett Wollman * kernel related system variables. 282c901836cSGarrett Wollman */ 2834b2af45fSPoul-Henning Kamp 284e21fa31aSGarrett Wollman /* 285e21fa31aSGarrett Wollman * This goop is here to support a loadable NFS module... grumble... 286e21fa31aSGarrett Wollman */ 287996c772fSJohn Dyson int (*lease_check_hook) __P((struct vop_lease_args *)) 288e21fa31aSGarrett Wollman = 0; 289e21fa31aSGarrett Wollman void (*lease_updatetime) __P((int)) 290e21fa31aSGarrett Wollman = 0; 291e21fa31aSGarrett Wollman 292996c772fSJohn Dyson int 293996c772fSJohn Dyson lease_check(ap) 294996c772fSJohn Dyson struct vop_lease_args /* { 295996c772fSJohn Dyson struct vnode *a_vp; 296996c772fSJohn Dyson struct proc *a_p; 297996c772fSJohn Dyson struct ucred *a_cred; 298996c772fSJohn Dyson int a_flag; 299996c772fSJohn Dyson } */ *ap; 300996c772fSJohn Dyson { 301996c772fSJohn Dyson if (lease_check_hook) 302996c772fSJohn Dyson return (*lease_check_hook)(ap); 303996c772fSJohn Dyson else 304996c772fSJohn Dyson return 0; 305996c772fSJohn Dyson } 306