Annotation of XNU/bsd/miscfs/volfs/volfs_vfsops.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) 1998 Apple Computer, Inc. All Rights Reserved */
                     23: /*
                     24:  * Change History:
                     25:  *
                     26:  *     29-May-1998     Pat Dirks       Changed to cache pointer to root vnode until unmount.
                     27:  *
                     28:  */
                     29: 
                     30: #include <sys/param.h>
                     31: #include <sys/systm.h>
                     32: #include <sys/namei.h>
                     33: #include <sys/proc.h>
                     34: #include <sys/kernel.h>
                     35: #include <mach/machine/vm_types.h>
                     36: #include <sys/vnode.h>
                     37: #include <sys/socket.h>
                     38: #include <sys/mount.h>
                     39: #include <sys/buf.h>
                     40: #include <sys/mbuf.h>
                     41: #include <sys/file.h>
                     42: #include <bsd/dev/disk.h>
                     43: #include <sys/ioctl.h>
                     44: #include <sys/errno.h>
                     45: #include <sys/malloc.h>
                     46: #include <dev/ldd.h>
                     47: 
                     48: #include <miscfs/specfs/specdev.h>
                     49: #include "volfs.h"
                     50: 
                     51: struct vfsops volfs_vfsops = {
                     52:        volfs_mount,
                     53:        volfs_start,
                     54:        volfs_unmount,
                     55:        volfs_root,
                     56:        volfs_quotactl,
                     57:        volfs_statfs,
                     58:        volfs_sync,
                     59:        volfs_vget,
                     60:        volfs_fhtovp,
                     61:        volfs_vptofh,
                     62:        volfs_init,
                     63:        volfs_sysctl
                     64: };
                     65: 
                     66: static char volfs_fs_name[MFSNAMELEN] = "volfs";
                     67: extern struct vnodeopv_desc volfs_vnodeop_opv_desc;
                     68: 
                     69: /* The following refer to kernel global variables used in the loading/initialization: */
                     70: extern int                      maxvfsslots;            /* Total number of slots in the system's vfsconf table */
                     71: extern int                      maxvfsconf;             /* The highest fs type number [old-style ID] in use [dispite its name] */
                     72: extern int                      vfs_opv_numops; /* The total number of defined vnode operations */
                     73: extern int kdp_flag;
                     74: 
                     75: void
                     76: volfs_load(int loadArgument) {
                     77:     struct vfsconf *vfsconflistentry;
                     78:     int entriesRemaining;
                     79:     struct vfsconf *newvfsconf = NULL;
                     80:     struct vfsconf *lastentry = NULL;
                     81:         int j;
                     82:         int (***opv_desc_vector_p)();
                     83:         int (**opv_desc_vector)();
                     84:         struct vnodeopv_entry_desc *opve_descp;
                     85: 
                     86: #pragma unused(loadArgument)
                     87: 
                     88:         /*
                     89:          * This routine is responsible for all the initialization that would
                     90:          * ordinarily be done as part of the system startup; it calls volfs_init
                     91:          * to do the initialization that is strictly volfs-specific.
                     92:          */
                     93: 
                     94:         /*
                     95:            prevvfsconf is supposed to be the entry preceding the new entry.
                     96:            To make sure we can always get hooked in SOMEWHERE in the list,
                     97:            start it out at the first entry of the list.  This assumes the
                     98:            first entry in the list will be non-empty and not volfs.
                     99: 
                    100:            This becomes irrelevant when volfs is compiled into the list.
                    101:          */
                    102:         DBG_VOP(("load_volfs: Scanning vfsconf list...\n"));
                    103:     vfsconflistentry = vfsconf;
                    104:     for (entriesRemaining = maxvfsslots; entriesRemaining > 0; --entriesRemaining) {
                    105:         if (vfsconflistentry->vfc_vfsops != NULL) {
                    106:             /*
                    107:              * Check to see if we're reloading a new version of volfs during debugging
                    108:              * and overwrite the previously assigned entry if we find one:
                    109:              */
                    110:             if (strcmp(vfsconflistentry->vfc_name, volfs_fs_name) == 0) {
                    111:                 newvfsconf = vfsconflistentry;
                    112:                 break;
                    113:             } else {
                    114:                 lastentry = vfsconflistentry;
                    115:             };
                    116:         } else {
                    117:             /*
                    118:              * This is at least a POSSIBLE place to insert the new entry...
                    119:              */
                    120:             newvfsconf = vfsconflistentry;
                    121:         };
                    122:         ++vfsconflistentry;
                    123:     };
                    124: 
                    125:     if (newvfsconf) {
                    126:                 DBG_VOP(("load_volfs: filling in vfsconf entry at 0x%08lX; lastentry = 0x%08lX.\n", (long)newvfsconf, (long)lastentry));
                    127:         newvfsconf->vfc_vfsops = &volfs_vfsops;
                    128:         strncpy(&newvfsconf->vfc_name[0], "volfs", MFSNAMELEN);
                    129:         newvfsconf->vfc_typenum = maxvfsconf++;
                    130:         newvfsconf->vfc_refcount = 0;
                    131:         newvfsconf->vfc_flags = 0;
                    132:         newvfsconf->vfc_mountroot = NULL;       /* Can't mount root of file system [yet] */
                    133: 
                    134:                 /* Hook into the list: */
                    135:         newvfsconf->vfc_next = NULL;
                    136:         if (lastentry) {
                    137:             newvfsconf->vfc_next = lastentry->vfc_next;
                    138:             lastentry->vfc_next = newvfsconf;
                    139:         };
                    140: 
                    141:         /* Based on vfs_op_init and ... */
                    142:         opv_desc_vector_p = volfs_vnodeop_opv_desc.opv_desc_vector_p;
                    143: 
                    144:         DBG_VOP(("load_volfs: Allocating and initializing VNode ops vector...\n"));
                    145: 
                    146:         /*
                    147:          * Allocate and init the vector.
                    148:          * Also handle backwards compatibility.
                    149:          */
                    150:         MALLOC(*opv_desc_vector_p, PFI *, vfs_opv_numops*sizeof(PFI), M_TEMP, M_WAITOK);
                    151: 
                    152:         bzero (*opv_desc_vector_p, vfs_opv_numops*sizeof(PFI));
                    153: 
                    154:         opv_desc_vector = *opv_desc_vector_p;
                    155:         for (j=0; volfs_vnodeop_opv_desc.opv_desc_ops[j].opve_op; j++) {
                    156:             opve_descp = &(volfs_vnodeop_opv_desc.opv_desc_ops[j]);
                    157: 
                    158:             /*
                    159:              * Sanity check:  is this operation listed
                    160:              * in the list of operations?  We check this
                    161:              * by seeing if its offest is zero.  Since
                    162:              * the default routine should always be listed
                    163:              * first, it should be the only one with a zero
                    164:              * offset.  Any other operation with a zero
                    165:              * offset is probably not listed in
                    166:              * vfs_op_descs, and so is probably an error.
                    167:              *
                    168:              * A panic here means the layer programmer
                    169:              * has committed the all-too common bug
                    170:              * of adding a new operation to the layer's
                    171:              * list of vnode operations but
                    172:              * not adding the operation to the system-wide
                    173:              * list of supported operations.
                    174:              */
                    175:             if (opve_descp->opve_op->vdesc_offset == 0 &&
                    176:                 opve_descp->opve_op->vdesc_offset != VOFFSET(vop_default)) {
                    177:                 DBG_VOP(("load_volfs: operation %s not listed in %s.\n",
                    178:                        opve_descp->opve_op->vdesc_name,
                    179:                        "vfs_op_descs"));
                    180:                 panic ("load_volfs: bad operation");
                    181:                 }
                    182:             /*
                    183:              * Fill in this entry.
                    184:              */
                    185:             opv_desc_vector[opve_descp->opve_op->vdesc_offset] =
                    186:                 opve_descp->opve_impl;
                    187:             }
                    188: 
                    189:         /*
                    190:          * Finally, go back and replace unfilled routines
                    191:          * with their default.  (Sigh, an O(n^3) algorithm.  I
                    192:                                  * could make it better, but that'd be work, and n is small.)
                    193:          */
                    194:         opv_desc_vector_p = volfs_vnodeop_opv_desc.opv_desc_vector_p;
                    195: 
                    196:         /*
                    197:          * Force every operations vector to have a default routine.
                    198:          */
                    199:         opv_desc_vector = *opv_desc_vector_p;
                    200:         if (opv_desc_vector[VOFFSET(vop_default)]==NULL) {
                    201:             panic("load_vp;fs: operation vector without default routine.");
                    202:             }
                    203:         for (j = 0;j<vfs_opv_numops; j++)
                    204:             if (opv_desc_vector[j] == NULL)
                    205:                 opv_desc_vector[j] =
                    206:                     opv_desc_vector[VOFFSET(vop_default)];
                    207: 
                    208:         DBG_VOP(("load_volfs: calling volfs_init()...\n"));
                    209:         volfs_init(newvfsconf);
                    210:         };
                    211: }
                    212: 
                    213: /*
                    214:  * VFS Operations.
                    215:  *
                    216:  * mount system call
                    217:  */
                    218: int
                    219: volfs_mount(mp, path, data, ndp, p)
                    220:        register struct mount *mp;
                    221:        char *path;
                    222:        caddr_t data;
                    223:        struct nameidata *ndp;
                    224:        struct proc *p;
                    225: {
                    226:        struct volfs_mntdata *priv_mnt_data;
                    227:     struct vnode *root_vp;
                    228:     struct volfs_vndata        *priv_vn_data;
                    229:     int        error;
                    230:     size_t size;
                    231: 
                    232:        DBG_VOP(("volfs_mount called\n"));
                    233:        MALLOC(priv_mnt_data, struct volfs_mntdata *, sizeof(struct volfs_mntdata),
                    234:                M_VOLFSMNT, M_WAITOK);
                    235:        DBG_VOP(("MALLOC succeeded\n"));
                    236:        LIST_INIT(&priv_mnt_data->volfs_fsvnodes);
                    237:        DBG_VOP(("LIST_INIT succeeded\n"));
                    238: 
                    239:        mp->mnt_data = (void *)priv_mnt_data;
                    240:        strcpy(mp->mnt_stat.f_fstypename, "volfs");
                    241:         (void) copyinstr(path, mp->mnt_stat.f_mntonname, sizeof(mp->mnt_stat.f_mntonname) - 1, &size);
                    242:        strcpy(mp->mnt_stat.f_mntfromname, "<volfs>");
                    243:        
                    244:        /* Set up the root vnode for fast reference in the future.
                    245:           Note that the root is maintained unlocked but with a pos. ref count until unmount. */
                    246:        
                    247:     MALLOC(priv_vn_data, struct volfs_vndata *, sizeof(struct volfs_vndata), M_VOLFSNODE, M_WAITOK);
                    248:     error = getnewvnode(VT_VOLFS, mp, volfs_vnodeop_p, &root_vp);
                    249:        if (error != 0)
                    250:        {
                    251:                FREE(priv_mnt_data, M_VOLFSMNT);
                    252:                FREE(priv_vn_data, M_VOLFSNODE);
                    253:                DBG_VOP(("getnewvnode failed with error code %d\n", error));
                    254:                return(error);
                    255:        }
                    256:     root_vp->v_type = VDIR;
                    257:     root_vp->v_flag = VROOT;
                    258:     lockinit(&priv_vn_data->lock, PINOD, "volfsnode", 0, 0);
                    259:     priv_vn_data->vnode_type = VOLFS_ROOT;
                    260:     priv_vn_data->nodeID = 0;
                    261:     priv_vn_data->fs_mount = mp;
                    262:     root_vp->v_data = priv_vn_data;
                    263: 
                    264:     priv_mnt_data->volfs_rootvp = root_vp;
                    265:        
                    266:     return (0);
                    267: }
                    268: 
                    269: int
                    270: volfs_start(mp, flags, p)
                    271: struct mount * mp;
                    272: int    flags;
                    273: struct proc * p;
                    274: {
                    275:        DBG_VOP(("volfs_start called\n"));
                    276:        return (0);
                    277: }
                    278: 
                    279: /*
                    280:  * Return the root of a filesystem.  For volfs the root vnode is a directory
                    281:  * containing the list of all filesystems volfs can work with.
                    282:  */
                    283: int
                    284: volfs_root(mp, vpp)
                    285:         struct mount *mp;
                    286:         struct vnode **vpp;
                    287: {
                    288:        struct volfs_mntdata *priv_data;
                    289:     // struct volfs_vndata     *priv_vn_data;
                    290:     // int     error;
                    291: 
                    292:     DBG_VOP(("volfs_root called\n"));
                    293:        priv_data = (struct volfs_mntdata *)mp->mnt_data;
                    294: 
                    295:     if (priv_data->volfs_rootvp) {
                    296:         vref(priv_data->volfs_rootvp);
                    297:         VOP_LOCK(priv_data->volfs_rootvp, LK_EXCLUSIVE, current_proc());
                    298:                *vpp = priv_data->volfs_rootvp;
                    299:        } else {
                    300:                panic("volfs: root vnode missing!");
                    301:     };
                    302:     
                    303:     DBG_VOP(("volfs_root returned with "));
                    304:     DBG_VOP_PRINT_VNODE_INFO(*vpp);DBG_VOP(("\n"));
                    305:     
                    306:     return(0);
                    307: }
                    308: 
                    309: int
                    310: volfs_quotactl(mp, cmds, uid, arg, p)
                    311: struct mount *mp;
                    312: int cmds;
                    313: uid_t uid;
                    314: caddr_t arg;
                    315: struct proc * p;
                    316: {
                    317:        DBG_VOP(("volfs_quotactl called\n"));
                    318:        return (0);
                    319: }
                    320: 
                    321: /*
                    322:  * unmount system call
                    323:  */
                    324: int
                    325: volfs_unmount(mp, mntflags, p)
                    326:        struct mount *mp;
                    327:        int mntflags;
                    328:        struct proc *p;
                    329: {
                    330:     struct     volfs_mntdata   *priv_data;
                    331:     struct vnode *root_vp;
                    332:     int                retval;
                    333: 
                    334:     DBG_VOP(("volfs_unmount called\n"));
                    335:     priv_data = (struct volfs_mntdata *)mp->mnt_data;
                    336: 
                    337:     root_vp = priv_data->volfs_rootvp;
                    338:     retval = vflush(mp, root_vp, 0);
                    339:     if (retval) goto Err_Exit;
                    340: 
                    341:     /* Free the root vnode.
                    342:          Note that there's no need to vget() or vref() it before locking it here:
                    343:          the ref. count has been maintained at +1 ever since mount time. */
                    344:     if (root_vp) {
                    345:         retval = vn_lock(root_vp, LK_EXCLUSIVE, p);
                    346:                if (retval) goto Err_Exit;
                    347:         if (root_vp->v_usecount > 1) {
                    348:             DBG_VOP(("VOLFS ERROR: root vnode = %x, usecount = %d\n", (int)root_vp, priv_data->volfs_rootvp->v_usecount));
                    349:             VOP_UNLOCK(root_vp, 0, p);
                    350:             retval = EBUSY;
                    351:             goto Err_Exit;
                    352:         };
                    353: 
                    354:         priv_data->volfs_rootvp = NULL;
                    355:         vput(root_vp);                         /* This drops volfs's own refcount */
                    356:         vgone(root_vp);
                    357:     };
                    358: 
                    359:        /* All vnodes should be gone, and no errors, clean up the last */
                    360:     /* XXX DBG_ASSERT(mp->mnt_vnodelist.lh_first == NULL); */
                    361:     /* XXX DBG_ASSERT(retval == 0); */
                    362: 
                    363:     mp->mnt_data = NULL;
                    364:     FREE(priv_data, M_VOLFSMNT);
                    365: 
                    366: Err_Exit:
                    367: 
                    368:     return(retval);
                    369: }
                    370: 
                    371: /*
                    372:  * Get file system statistics.
                    373:  */
                    374: int
                    375: volfs_statfs(mp, sbp, p)
                    376:        struct mount *mp;
                    377:        register struct statfs *sbp;
                    378:        struct proc *p;
                    379: {
                    380:        DBG_VOP(("volfs_statfs called\n"));
                    381:        sbp->f_bsize = 512;
                    382:        sbp->f_iosize = 512;
                    383:        sbp->f_blocks = 1024;   // lies, darn lies and virtual file systems
                    384:        sbp->f_bfree = 0;       // Nope, can't write here!
                    385:        sbp->f_bavail = 0;
                    386:        sbp->f_files =  0;      // Hmmm...maybe later
                    387:        sbp->f_ffree = 0;
                    388:        return (0);
                    389: }
                    390: 
                    391: /*
                    392:  * volfs doesn't have any data and you can't write into any of the volfs 
                    393:  * structures, so don't do anything
                    394:  */
                    395: int
                    396: volfs_sync(mp, waitfor, cred, p)
                    397:        struct mount *mp;
                    398:        int waitfor;
                    399:        struct ucred *cred;
                    400:        struct proc *p;
                    401: {
                    402: //     DBG_VOP(("volfs_sync called\n"));
                    403:        return 0;
                    404: }
                    405: /*
                    406:  * Look up a FFS dinode number to find its incore vnode, otherwise read it
                    407:  * in from disk.  If it is in core, wait for the lock bit to clear, then
                    408:  * return the inode locked.  Detection and handling of mount points must be
                    409:  * done by the calling routine.
                    410:  */
                    411: int
                    412: volfs_vget(mp, ino, vpp)
                    413:        struct mount *mp;
                    414:        void *ino;
                    415:        struct vnode **vpp;
                    416: {
                    417: //     DBG_VOP(("volfs_vget called\n"));
                    418:        return(0);
                    419: }
                    420: /*
                    421:  * File handle to vnode
                    422:  *
                    423:  * Have to be really careful about stale file handles:
                    424:  * - check that the inode number is valid
                    425:  * - call ffs_vget() to get the locked inode
                    426:  * - check for an unallocated inode (i_mode == 0)
                    427:  * - check that the given client host has export rights and return
                    428:  *   those rights via. exflagsp and credanonp
                    429:  */
                    430: int
                    431: volfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
                    432:        register struct mount *mp;
                    433:        struct fid *fhp;
                    434:        struct mbuf *nam;
                    435:        struct vnode **vpp;
                    436:        int *exflagsp;
                    437:        struct ucred **credanonp;
                    438: {
                    439:        DBG_VOP(("volfs_fhtovp called\n"));
                    440:        return(0);
                    441: }
                    442: /*
                    443:  * Vnode pointer to File handle
                    444:  */
                    445: /* ARGSUSED */
                    446: int
                    447: volfs_vptofh(vp, fhp)
                    448:        struct vnode *vp;
                    449:        struct fid *fhp;
                    450: {
                    451:        DBG_VOP(("volfs_vptofh called\n"));
                    452:        return(0);
                    453: }
                    454: /*
                    455:  * Initialize the filesystem
                    456:  */
                    457: int
                    458: volfs_init(vfsp)
                    459:        struct vfsconf *vfsp;
                    460: {
                    461:        DBG_VOP(("volfs_init called\n"));
                    462:        return (0);
                    463: }
                    464: 
                    465: /*
                    466:  * fast filesystem related variables.
                    467:  */
                    468: int
                    469: volfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                    470:        int *name;
                    471:        u_int namelen;
                    472:        void *oldp;
                    473:        size_t *oldlenp;
                    474:        void *newp;
                    475:        size_t newlen;
                    476:        struct proc *p;
                    477: {
                    478:        DBG_VOP(("volfs_sysctl called\n"));
                    479:        return (EOPNOTSUPP);
                    480: }
                    481: 

unix.superglobalmegacorp.com

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