Annotation of XNU/bsd/miscfs/volfs/volfs_vfsops.c, revision 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.