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 39c901836cSGarrett Wollman * $Id: vfs_init.c,v 1.4 1994/08/18 22:35:08 wollman 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/time.h> 48df8bae1dSRodney W. Grimes #include <sys/vnode.h> 49df8bae1dSRodney W. Grimes #include <sys/stat.h> 50df8bae1dSRodney W. Grimes #include <sys/namei.h> 51df8bae1dSRodney W. Grimes #include <sys/ucred.h> 52df8bae1dSRodney W. Grimes #include <sys/buf.h> 53df8bae1dSRodney W. Grimes #include <sys/errno.h> 54df8bae1dSRodney W. Grimes #include <sys/malloc.h> 55c901836cSGarrett Wollman #include <sys/proc.h> 56c901836cSGarrett Wollman #include <vm/vm.h> 57c901836cSGarrett Wollman #include <sys/sysctl.h> 58df8bae1dSRodney W. Grimes 59df8bae1dSRodney W. Grimes /* 60df8bae1dSRodney W. Grimes * Sigh, such primitive tools are these... 61df8bae1dSRodney W. Grimes */ 62df8bae1dSRodney W. Grimes #if 0 63df8bae1dSRodney W. Grimes #define DODEBUG(A) A 64df8bae1dSRodney W. Grimes #else 65df8bae1dSRodney W. Grimes #define DODEBUG(A) 66df8bae1dSRodney W. Grimes #endif 67df8bae1dSRodney W. Grimes 68c901836cSGarrett Wollman struct vfsconf void_vfsconf; 69c901836cSGarrett Wollman 70c901836cSGarrett Wollman extern struct linker_set vfs_opv_descs_; 71c901836cSGarrett Wollman #define vfs_opv_descs ((struct vnodeopv_desc **)vfs_opv_descs_.ls_items) 72c901836cSGarrett Wollman 73c901836cSGarrett Wollman extern struct linker_set vfs_set; 74c901836cSGarrett Wollman struct vfsops *vfssw[MOUNT_MAXTYPE + 1]; 75c901836cSGarrett Wollman struct vfsconf *vfsconf[MOUNT_MAXTYPE + 1]; 76c901836cSGarrett Wollman 77df8bae1dSRodney W. Grimes extern struct vnodeop_desc *vfs_op_descs[]; 78df8bae1dSRodney W. Grimes /* and the operations they perform */ 79df8bae1dSRodney W. Grimes /* 80df8bae1dSRodney W. Grimes * This code doesn't work if the defn is **vnodop_defns with cc. 81df8bae1dSRodney W. Grimes * The problem is because of the compiler sometimes putting in an 82df8bae1dSRodney W. Grimes * extra level of indirection for arrays. It's an interesting 83df8bae1dSRodney W. Grimes * "feature" of C. 84df8bae1dSRodney W. Grimes */ 85df8bae1dSRodney W. Grimes int vfs_opv_numops; 86df8bae1dSRodney W. Grimes 87c901836cSGarrett Wollman typedef int (*PFI)(); /* the standard Pointer to a Function returning an Int */ 88df8bae1dSRodney W. Grimes 89df8bae1dSRodney W. Grimes /* 90df8bae1dSRodney W. Grimes * A miscellaneous routine. 91df8bae1dSRodney W. Grimes * A generic "default" routine that just returns an error. 92df8bae1dSRodney W. Grimes */ 93df8bae1dSRodney W. Grimes int 94df8bae1dSRodney W. Grimes vn_default_error() 95df8bae1dSRodney W. Grimes { 96df8bae1dSRodney W. Grimes 97df8bae1dSRodney W. Grimes return (EOPNOTSUPP); 98df8bae1dSRodney W. Grimes } 99df8bae1dSRodney W. Grimes 100df8bae1dSRodney W. Grimes /* 101df8bae1dSRodney W. Grimes * vfs_init.c 102df8bae1dSRodney W. Grimes * 103df8bae1dSRodney W. Grimes * Allocate and fill in operations vectors. 104df8bae1dSRodney W. Grimes * 105df8bae1dSRodney W. Grimes * An undocumented feature of this approach to defining operations is that 106df8bae1dSRodney W. Grimes * there can be multiple entries in vfs_opv_descs for the same operations 107df8bae1dSRodney W. Grimes * vector. This allows third parties to extend the set of operations 108df8bae1dSRodney W. Grimes * supported by another layer in a binary compatibile way. For example, 109df8bae1dSRodney W. Grimes * assume that NFS needed to be modified to support Ficus. NFS has an entry 110df8bae1dSRodney W. Grimes * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by 111df8bae1dSRodney W. Grimes * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions) 112df8bae1dSRodney W. Grimes * listing those new operations Ficus adds to NFS, all without modifying the 113df8bae1dSRodney W. Grimes * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but 114df8bae1dSRodney W. Grimes * that is a(whole)nother story.) This is a feature. 115df8bae1dSRodney W. Grimes */ 116df8bae1dSRodney W. Grimes void 117c901836cSGarrett Wollman vfs_opv_init(struct vnodeopv_desc **them) 118df8bae1dSRodney W. Grimes { 119df8bae1dSRodney W. Grimes int i, j, k; 120df8bae1dSRodney W. Grimes int (***opv_desc_vector_p)(); 121df8bae1dSRodney W. Grimes int (**opv_desc_vector)(); 122df8bae1dSRodney W. Grimes struct vnodeopv_entry_desc *opve_descp; 123df8bae1dSRodney W. Grimes 124df8bae1dSRodney W. Grimes /* 125df8bae1dSRodney W. Grimes * Allocate the dynamic vectors and fill them in. 126df8bae1dSRodney W. Grimes */ 127c901836cSGarrett Wollman for (i=0; them[i]; i++) { 128c901836cSGarrett Wollman opv_desc_vector_p = them[i]->opv_desc_vector_p; 129df8bae1dSRodney W. Grimes /* 130df8bae1dSRodney W. Grimes * Allocate and init the vector, if it needs it. 131df8bae1dSRodney W. Grimes * Also handle backwards compatibility. 132df8bae1dSRodney W. Grimes */ 133df8bae1dSRodney W. Grimes if (*opv_desc_vector_p == NULL) { 134df8bae1dSRodney W. Grimes /* XXX - shouldn't be M_VNODE */ 135df8bae1dSRodney W. Grimes MALLOC(*opv_desc_vector_p, PFI*, 136df8bae1dSRodney W. Grimes vfs_opv_numops*sizeof(PFI), M_VNODE, M_WAITOK); 137df8bae1dSRodney W. Grimes bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI)); 138df8bae1dSRodney W. Grimes DODEBUG(printf("vector at %x allocated\n", 139df8bae1dSRodney W. Grimes opv_desc_vector_p)); 140df8bae1dSRodney W. Grimes } 141df8bae1dSRodney W. Grimes opv_desc_vector = *opv_desc_vector_p; 142c901836cSGarrett Wollman for (j=0; them[i]->opv_desc_ops[j].opve_op; j++) { 143c901836cSGarrett Wollman opve_descp = &(them[i]->opv_desc_ops[j]); 144df8bae1dSRodney W. Grimes 145df8bae1dSRodney W. Grimes /* 146df8bae1dSRodney W. Grimes * Sanity check: is this operation listed 147df8bae1dSRodney W. Grimes * in the list of operations? We check this 148df8bae1dSRodney W. Grimes * by seeing if its offest is zero. Since 149df8bae1dSRodney W. Grimes * the default routine should always be listed 150df8bae1dSRodney W. Grimes * first, it should be the only one with a zero 151df8bae1dSRodney W. Grimes * offset. Any other operation with a zero 152df8bae1dSRodney W. Grimes * offset is probably not listed in 153df8bae1dSRodney W. Grimes * vfs_op_descs, and so is probably an error. 154df8bae1dSRodney W. Grimes * 155df8bae1dSRodney W. Grimes * A panic here means the layer programmer 156df8bae1dSRodney W. Grimes * has committed the all-too common bug 157df8bae1dSRodney W. Grimes * of adding a new operation to the layer's 158df8bae1dSRodney W. Grimes * list of vnode operations but 159df8bae1dSRodney W. Grimes * not adding the operation to the system-wide 160df8bae1dSRodney W. Grimes * list of supported operations. 161df8bae1dSRodney W. Grimes */ 162df8bae1dSRodney W. Grimes if (opve_descp->opve_op->vdesc_offset == 0 && 163df8bae1dSRodney W. Grimes opve_descp->opve_op->vdesc_offset != 164df8bae1dSRodney W. Grimes VOFFSET(vop_default)) { 165df8bae1dSRodney W. Grimes printf("operation %s not listed in %s.\n", 166df8bae1dSRodney W. Grimes opve_descp->opve_op->vdesc_name, 167df8bae1dSRodney W. Grimes "vfs_op_descs"); 168df8bae1dSRodney W. Grimes panic ("vfs_opv_init: bad operation"); 169df8bae1dSRodney W. Grimes } 170df8bae1dSRodney W. Grimes /* 171df8bae1dSRodney W. Grimes * Fill in this entry. 172df8bae1dSRodney W. Grimes */ 173df8bae1dSRodney W. Grimes opv_desc_vector[opve_descp->opve_op->vdesc_offset] = 174df8bae1dSRodney W. Grimes opve_descp->opve_impl; 175df8bae1dSRodney W. Grimes } 176df8bae1dSRodney W. Grimes } 177df8bae1dSRodney W. Grimes /* 178df8bae1dSRodney W. Grimes * Finally, go back and replace unfilled routines 179df8bae1dSRodney W. Grimes * with their default. (Sigh, an O(n^3) algorithm. I 180df8bae1dSRodney W. Grimes * could make it better, but that'd be work, and n is small.) 181df8bae1dSRodney W. Grimes */ 182c901836cSGarrett Wollman for (i = 0; them[i]; i++) { 183c901836cSGarrett Wollman opv_desc_vector = *(them[i]->opv_desc_vector_p); 184df8bae1dSRodney W. Grimes /* 185df8bae1dSRodney W. Grimes * Force every operations vector to have a default routine. 186df8bae1dSRodney W. Grimes */ 187df8bae1dSRodney W. Grimes if (opv_desc_vector[VOFFSET(vop_default)]==NULL) { 188df8bae1dSRodney W. Grimes panic("vfs_opv_init: operation vector without default routine."); 189df8bae1dSRodney W. Grimes } 190df8bae1dSRodney W. Grimes for (k = 0; k<vfs_opv_numops; k++) 191df8bae1dSRodney W. Grimes if (opv_desc_vector[k] == NULL) 192df8bae1dSRodney W. Grimes opv_desc_vector[k] = 193df8bae1dSRodney W. Grimes opv_desc_vector[VOFFSET(vop_default)]; 194df8bae1dSRodney W. Grimes } 195df8bae1dSRodney W. Grimes } 196df8bae1dSRodney W. Grimes 197df8bae1dSRodney W. Grimes /* 198df8bae1dSRodney W. Grimes * Initialize known vnode operations vectors. 199df8bae1dSRodney W. Grimes */ 200df8bae1dSRodney W. Grimes void 201df8bae1dSRodney W. Grimes vfs_op_init() 202df8bae1dSRodney W. Grimes { 203df8bae1dSRodney W. Grimes int i; 204df8bae1dSRodney W. Grimes 205df8bae1dSRodney W. Grimes DODEBUG(printf("Vnode_interface_init.\n")); 206df8bae1dSRodney W. Grimes /* 207df8bae1dSRodney W. Grimes * Set all vnode vectors to a well known value. 208df8bae1dSRodney W. Grimes */ 209df8bae1dSRodney W. Grimes for (i = 0; vfs_opv_descs[i]; i++) 210df8bae1dSRodney W. Grimes *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL; 211df8bae1dSRodney W. Grimes /* 212df8bae1dSRodney W. Grimes * Figure out how many ops there are by counting the table, 213df8bae1dSRodney W. Grimes * and assign each its offset. 214df8bae1dSRodney W. Grimes */ 215df8bae1dSRodney W. Grimes for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) { 216df8bae1dSRodney W. Grimes vfs_op_descs[i]->vdesc_offset = vfs_opv_numops; 217df8bae1dSRodney W. Grimes vfs_opv_numops++; 218df8bae1dSRodney W. Grimes } 219df8bae1dSRodney W. Grimes DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops)); 220df8bae1dSRodney W. Grimes } 221df8bae1dSRodney W. Grimes 222df8bae1dSRodney W. Grimes /* 223df8bae1dSRodney W. Grimes * Routines having to do with the management of the vnode table. 224df8bae1dSRodney W. Grimes */ 225df8bae1dSRodney W. Grimes extern struct vnodeops dead_vnodeops; 226df8bae1dSRodney W. Grimes extern struct vnodeops spec_vnodeops; 227df8bae1dSRodney W. Grimes extern void vclean(); 228df8bae1dSRodney W. Grimes struct vattr va_null; 229df8bae1dSRodney W. Grimes 230df8bae1dSRodney W. Grimes /* 231df8bae1dSRodney W. Grimes * Initialize the vnode structures and initialize each file system type. 232df8bae1dSRodney W. Grimes */ 23326f9a767SRodney W. Grimes void 234df8bae1dSRodney W. Grimes vfsinit() 235df8bae1dSRodney W. Grimes { 236df8bae1dSRodney W. Grimes struct vfsops **vfsp; 237c901836cSGarrett Wollman struct vfsconf **vfc; 238c901836cSGarrett Wollman int i; 239c901836cSGarrett Wollman 240c901836cSGarrett Wollman /* 241c901836cSGarrett Wollman * Initialize the VFS switch table 242c901836cSGarrett Wollman */ 243c901836cSGarrett Wollman for(i = 0; i < MOUNT_MAXTYPE + 1; i++) { 244c901836cSGarrett Wollman vfsconf[i] = &void_vfsconf; 245c901836cSGarrett Wollman } 246c901836cSGarrett Wollman 247c901836cSGarrett Wollman vfc = (struct vfsconf **)vfs_set.ls_items; 248c901836cSGarrett Wollman while(*vfc) { 249c901836cSGarrett Wollman vfssw[(**vfc).vfc_index] = (**vfc).vfc_vfsops; 250c901836cSGarrett Wollman vfsconf[(**vfc).vfc_index] = *vfc; 251c901836cSGarrett Wollman vfc++; 252c901836cSGarrett Wollman } 253df8bae1dSRodney W. Grimes 254df8bae1dSRodney W. Grimes /* 255df8bae1dSRodney W. Grimes * Initialize the vnode table 256df8bae1dSRodney W. Grimes */ 257df8bae1dSRodney W. Grimes vntblinit(); 258df8bae1dSRodney W. Grimes /* 259df8bae1dSRodney W. Grimes * Initialize the vnode name cache 260df8bae1dSRodney W. Grimes */ 261df8bae1dSRodney W. Grimes nchinit(); 262df8bae1dSRodney W. Grimes /* 263df8bae1dSRodney W. Grimes * Build vnode operation vectors. 264df8bae1dSRodney W. Grimes */ 265df8bae1dSRodney W. Grimes vfs_op_init(); 266c901836cSGarrett Wollman vfs_opv_init(vfs_opv_descs); /* finish the job */ 267df8bae1dSRodney W. Grimes /* 268df8bae1dSRodney W. Grimes * Initialize each file system type. 269df8bae1dSRodney W. Grimes */ 270df8bae1dSRodney W. Grimes vattr_null(&va_null); 271df8bae1dSRodney W. Grimes for (vfsp = &vfssw[0]; vfsp <= &vfssw[MOUNT_MAXTYPE]; vfsp++) { 272df8bae1dSRodney W. Grimes if (*vfsp == NULL) 273df8bae1dSRodney W. Grimes continue; 274df8bae1dSRodney W. Grimes (*(*vfsp)->vfs_init)(); 275df8bae1dSRodney W. Grimes } 276df8bae1dSRodney W. Grimes } 277c901836cSGarrett Wollman 278c901836cSGarrett Wollman /* 279c901836cSGarrett Wollman * kernel related system variables. 280c901836cSGarrett Wollman */ 281c901836cSGarrett Wollman int 282c901836cSGarrett Wollman fs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 283c901836cSGarrett Wollman int *name; 284c901836cSGarrett Wollman u_int namelen; 285c901836cSGarrett Wollman void *oldp; 286c901836cSGarrett Wollman size_t *oldlenp; 287c901836cSGarrett Wollman void *newp; 288c901836cSGarrett Wollman size_t newlen; 289c901836cSGarrett Wollman struct proc *p; 290c901836cSGarrett Wollman { 291c901836cSGarrett Wollman int i; 292c901836cSGarrett Wollman int error; 293c901836cSGarrett Wollman int buflen = *oldlenp; 294c901836cSGarrett Wollman caddr_t where = newp, start = newp; 295c901836cSGarrett Wollman 296c901836cSGarrett Wollman switch (name[0]) { 297c901836cSGarrett Wollman case FS_VFSCONF: 298c901836cSGarrett Wollman if (namelen != 1) return ENOTDIR; 299c901836cSGarrett Wollman 300c901836cSGarrett Wollman if (oldp == NULL) { 301c901836cSGarrett Wollman *oldlenp = (MOUNT_MAXTYPE+1) * sizeof(struct vfsconf); 302c901836cSGarrett Wollman return 0; 303c901836cSGarrett Wollman } 304c901836cSGarrett Wollman if (newp) { 305c901836cSGarrett Wollman return EINVAL; 306c901836cSGarrett Wollman } 307c901836cSGarrett Wollman 308c901836cSGarrett Wollman for(i = 0; i < MOUNT_MAXTYPE + 1; i++) { 309c901836cSGarrett Wollman if(buflen < sizeof *vfsconf[i]) { 310c901836cSGarrett Wollman *oldlenp = where - start; 311c901836cSGarrett Wollman return ENOMEM; 312c901836cSGarrett Wollman } 313c901836cSGarrett Wollman 314c901836cSGarrett Wollman if(error = copyout(vfsconf[i], where, 315c901836cSGarrett Wollman sizeof *vfsconf[i])) 316c901836cSGarrett Wollman return error; 317c901836cSGarrett Wollman where += sizeof *vfsconf[i]; 318c901836cSGarrett Wollman buflen -= sizeof *vfsconf[i]; 319c901836cSGarrett Wollman } 320c901836cSGarrett Wollman *oldlenp = where - start; 321c901836cSGarrett Wollman return 0; 322c901836cSGarrett Wollman 323c901836cSGarrett Wollman default: 324c901836cSGarrett Wollman return (EOPNOTSUPP); 325c901836cSGarrett Wollman } 326c901836cSGarrett Wollman /* NOTREACHED */ 327c901836cSGarrett Wollman } 328c901836cSGarrett Wollman 329