Annotation of XNU/bsd/vfs/vfs_init.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     23: /*
                     24:  * Copyright (c) 1989, 1993
                     25:  *     The Regents of the University of California.  All rights reserved.
                     26:  *
                     27:  * This code is derived from software contributed
                     28:  * to Berkeley by John Heidemann of the UCLA Ficus project.
                     29:  *
                     30:  * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
                     31:  *
                     32:  * Redistribution and use in source and binary forms, with or without
                     33:  * modification, are permitted provided that the following conditions
                     34:  * are met:
                     35:  * 1. Redistributions of source code must retain the above copyright
                     36:  *    notice, this list of conditions and the following disclaimer.
                     37:  * 2. Redistributions in binary form must reproduce the above copyright
                     38:  *    notice, this list of conditions and the following disclaimer in the
                     39:  *    documentation and/or other materials provided with the distribution.
                     40:  * 3. All advertising materials mentioning features or use of this software
                     41:  *    must display the following acknowledgement:
                     42:  *     This product includes software developed by the University of
                     43:  *     California, Berkeley and its contributors.
                     44:  * 4. Neither the name of the University nor the names of its contributors
                     45:  *    may be used to endorse or promote products derived from this software
                     46:  *    without specific prior written permission.
                     47:  *
                     48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     58:  * SUCH DAMAGE.
                     59:  *
                     60:  *     @(#)vfs_init.c  8.5 (Berkeley) 5/11/95
                     61:  */
                     62: 
                     63: 
                     64: #include <sys/param.h>
                     65: #include <sys/mount.h>
                     66: #include <sys/time.h>
                     67: #include <sys/vm.h>
                     68: #include <sys/vnode.h>
                     69: #include <sys/stat.h>
                     70: #include <sys/namei.h>
                     71: #include <sys/ucred.h>
                     72: #include <sys/buf.h>
                     73: #include <sys/errno.h>
                     74: #include <sys/malloc.h>
                     75: 
                     76: 
                     77: /*
                     78:  * Sigh, such primitive tools are these...
                     79:  */
                     80: #if 0
                     81: #define DODEBUG(A) A
                     82: #else
                     83: #define DODEBUG(A)
                     84: #endif
                     85: 
                     86: extern struct vnodeopv_desc *vfs_opv_descs[];
                     87:                                /* a list of lists of vnodeops defns */
                     88: extern struct vnodeop_desc *vfs_op_descs[];
                     89:                                /* and the operations they perform */
                     90: /*
                     91:  * This code doesn't work if the defn is **vnodop_defns with cc.
                     92:  * The problem is because of the compiler sometimes putting in an
                     93:  * extra level of indirection for arrays.  It's an interesting
                     94:  * "feature" of C.
                     95:  */
                     96: int vfs_opv_numops;
                     97: 
                     98: typedef (*PFI)();   /* the standard Pointer to a Function returning an Int */
                     99: 
                    100: /*
                    101:  * A miscellaneous routine.
                    102:  * A generic "default" routine that just returns an error.
                    103:  */
                    104: int
                    105: vn_default_error()
                    106: {
                    107: 
                    108:        return (EOPNOTSUPP);
                    109: }
                    110: 
                    111: /*
                    112:  * vfs_init.c
                    113:  *
                    114:  * Allocate and fill in operations vectors.
                    115:  *
                    116:  * An undocumented feature of this approach to defining operations is that
                    117:  * there can be multiple entries in vfs_opv_descs for the same operations
                    118:  * vector. This allows third parties to extend the set of operations
                    119:  * supported by another layer in a binary compatibile way. For example,
                    120:  * assume that NFS needed to be modified to support Ficus. NFS has an entry
                    121:  * (probably nfs_vnopdeop_decls) declaring all the operations NFS supports by
                    122:  * default. Ficus could add another entry (ficus_nfs_vnodeop_decl_entensions)
                    123:  * listing those new operations Ficus adds to NFS, all without modifying the
                    124:  * NFS code. (Of couse, the OTW NFS protocol still needs to be munged, but
                    125:  * that is a(whole)nother story.) This is a feature.
                    126:  */
                    127: void
                    128: vfs_opv_init()
                    129: {
                    130:        int i, j, k;
                    131:        int (***opv_desc_vector_p)();
                    132:        int (**opv_desc_vector)();
                    133:        struct vnodeopv_entry_desc *opve_descp;
                    134: 
                    135:        /*
                    136:         * Allocate the dynamic vectors and fill them in.
                    137:         */
                    138:        for (i=0; vfs_opv_descs[i]; i++) {
                    139:                opv_desc_vector_p = vfs_opv_descs[i]->opv_desc_vector_p;
                    140:                /*
                    141:                 * Allocate and init the vector, if it needs it.
                    142:                 * Also handle backwards compatibility.
                    143:                 */
                    144:                if (*opv_desc_vector_p == NULL) {
                    145:                        /* XXX - shouldn't be M_VNODE */
                    146:                        MALLOC(*opv_desc_vector_p, PFI*,
                    147:                               vfs_opv_numops*sizeof(PFI), M_VNODE, M_WAITOK);
                    148:                        bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI));
                    149:                        DODEBUG(printf("vector at %x allocated\n",
                    150:                            opv_desc_vector_p));
                    151:                }
                    152:                opv_desc_vector = *opv_desc_vector_p;
                    153:                for (j=0; vfs_opv_descs[i]->opv_desc_ops[j].opve_op; j++) {
                    154:                        opve_descp = &(vfs_opv_descs[i]->opv_desc_ops[j]);
                    155: 
                    156:                        /*
                    157:                         * Sanity check:  is this operation listed
                    158:                         * in the list of operations?  We check this
                    159:                         * by seeing if its offest is zero.  Since
                    160:                         * the default routine should always be listed
                    161:                         * first, it should be the only one with a zero
                    162:                         * offset.  Any other operation with a zero
                    163:                         * offset is probably not listed in
                    164:                         * vfs_op_descs, and so is probably an error.
                    165:                         *
                    166:                         * A panic here means the layer programmer
                    167:                         * has committed the all-too common bug
                    168:                         * of adding a new operation to the layer's
                    169:                         * list of vnode operations but
                    170:                         * not adding the operation to the system-wide
                    171:                         * list of supported operations.
                    172:                         */
                    173:                        if (opve_descp->opve_op->vdesc_offset == 0 &&
                    174:                                    opve_descp->opve_op->vdesc_offset !=
                    175:                                        VOFFSET(vop_default)) {
                    176:                                printf("operation %s not listed in %s.\n",
                    177:                                    opve_descp->opve_op->vdesc_name,
                    178:                                    "vfs_op_descs");
                    179:                                panic ("vfs_opv_init: bad operation");
                    180:                        }
                    181:                        /*
                    182:                         * Fill in this entry.
                    183:                         */
                    184:                        opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
                    185:                                        opve_descp->opve_impl;
                    186:                }
                    187:        }
                    188:        /*
                    189:         * Finally, go back and replace unfilled routines
                    190:         * with their default.  (Sigh, an O(n^3) algorithm.  I
                    191:         * could make it better, but that'd be work, and n is small.)
                    192:         */
                    193:        for (i = 0; vfs_opv_descs[i]; i++) {
                    194:                opv_desc_vector = *(vfs_opv_descs[i]->opv_desc_vector_p);
                    195:                /*
                    196:                 * Force every operations vector to have a default routine.
                    197:                 */
                    198:                if (opv_desc_vector[VOFFSET(vop_default)]==NULL) {
                    199:                        panic("vfs_opv_init: operation vector without default routine.");
                    200:                }
                    201:                for (k = 0; k<vfs_opv_numops; k++)
                    202:                        if (opv_desc_vector[k] == NULL)
                    203:                                opv_desc_vector[k] = 
                    204:                                        opv_desc_vector[VOFFSET(vop_default)];
                    205:        }
                    206: }
                    207: 
                    208: /*
                    209:  * Initialize known vnode operations vectors.
                    210:  */
                    211: void
                    212: vfs_op_init()
                    213: {
                    214:        int i;
                    215: 
                    216:        DODEBUG(printf("Vnode_interface_init.\n"));
                    217:        /*
                    218:         * Set all vnode vectors to a well known value.
                    219:         */
                    220:        for (i = 0; vfs_opv_descs[i]; i++)
                    221:                *(vfs_opv_descs[i]->opv_desc_vector_p) = NULL;
                    222:        /*
                    223:         * Figure out how many ops there are by counting the table,
                    224:         * and assign each its offset.
                    225:         */
                    226:        for (vfs_opv_numops = 0, i = 0; vfs_op_descs[i]; i++) {
                    227:                vfs_op_descs[i]->vdesc_offset = vfs_opv_numops;
                    228:                vfs_opv_numops++;
                    229:        }
                    230:        DODEBUG(printf ("vfs_opv_numops=%d\n", vfs_opv_numops));
                    231: }
                    232: 
                    233: /*
                    234:  * Routines having to do with the management of the vnode table.
                    235:  */
                    236: extern struct vnodeops dead_vnodeops;
                    237: extern struct vnodeops spec_vnodeops;
                    238: struct vattr va_null;
                    239: 
                    240: /*
                    241:  * Initialize the vnode structures and initialize each file system type.
                    242:  */
                    243: vfsinit()
                    244: {
                    245:        struct vfsconf *vfsp;
                    246:        int i, maxtypenum;
                    247: 
                    248:        /*
                    249:         * Initialize the vnode table
                    250:         */
                    251:        vntblinit();
                    252:        /*
                    253:         * Initialize the vnode name cache
                    254:         */
                    255:        nchinit();
                    256:        /*
                    257:         * Build vnode operation vectors.
                    258:         */
                    259:        vfs_op_init();
                    260:        vfs_opv_init();   /* finish the job */
                    261:        /*
                    262:         * Initialize each file system type.
                    263:         */
                    264:        vattr_null(&va_null);
                    265:        numused_vfsslots = maxtypenum = 0;
                    266:        for (vfsp = vfsconf, i = 0; i < maxvfsconf; i++, vfsp++) {
                    267:                if (vfsp->vfc_vfsops == (struct vfsops *)0)
                    268:                        break;
                    269:                if (i) vfsconf[i-1].vfc_next = vfsp;
                    270:                if (maxtypenum <= vfsp->vfc_typenum)
                    271:                        maxtypenum = vfsp->vfc_typenum + 1;
                    272:                (*vfsp->vfc_vfsops->vfs_init)(vfsp);
                    273:                numused_vfsslots++;
                    274:        }
                    275:        /* next vfc_typenum to be used */
                    276:        maxvfsconf = maxtypenum;
                    277: }
                    278: 
                    279: int vfsconf_add(struct vfsconf *nvfsp)
                    280: {
                    281:        struct vfsconf *vfsp;
                    282: 
                    283:        if ((numused_vfsslots >= maxvfsslots) || (nvfsp == (struct vfsconf *)0))
                    284:                return (-1);
                    285:        bcopy(nvfsp, &vfsconf[numused_vfsslots], sizeof(struct vfsconf));
                    286:        vfsconf[numused_vfsslots-1].vfc_next = &vfsconf[numused_vfsslots];
                    287:        
                    288:        if (nvfsp->vfc_typenum <= maxvfsconf )
                    289:                        maxvfsconf = nvfsp->vfc_typenum + 1;
                    290:        numused_vfsslots++;
                    291:        if (nvfsp->vfc_vfsops->vfs_init)
                    292:                (*nvfsp->vfc_vfsops->vfs_init)(nvfsp);
                    293:        return(0);
                    294: }
                    295: 
                    296: int vfsconf_del(char * fs_name)
                    297: {
                    298: int entriesRemaining;
                    299:     struct vfsconf *vfsconflistentry;
                    300:     struct vfsconf *prevconf = NULL;
                    301:     struct vfsconf *targetconf = NULL;
                    302: 
                    303:     prevconf = vfsconflistentry = vfsconf;
                    304:     for (entriesRemaining = maxvfsslots;
                    305:          (entriesRemaining > 0) && (vfsconflistentry != NULL);
                    306:          --entriesRemaining) {
                    307:         if ((vfsconflistentry->vfc_vfsops != NULL) && (strcmp(vfsconflistentry->vfc_name, fs_name) == 0)) {
                    308:             targetconf = vfsconflistentry;
                    309:             break;
                    310:         };
                    311:         prevconf = vfsconflistentry;
                    312:         vfsconflistentry = vfsconflistentry->vfc_next;
                    313:     };
                    314: 
                    315:     if (targetconf != NULL) {
                    316:         if (prevconf != NULL) {
                    317:             /* Unlink the target entry from the list: 
                    318:               and decrement our count                */
                    319:             prevconf->vfc_next = targetconf->vfc_next;
                    320:            numused_vfsslots--;
                    321:         } else {
                    322:            /* XXX need real error code for no previous entry in list */
                    323:             return(-1);
                    324:         }
                    325:     } else {
                    326:           /* XXX need real error code for entry not found */
                    327:           return(-1);
                    328:     };
                    329:        return(0);
                    330: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.