Annotation of XNU/bsd/miscfs/volfs/volfs_vnops.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: /*
        !            23:  * Copyright (c) 1998-1999 Apple Computer, Inc. All Rights Reserved.
        !            24:  *
        !            25:  *     Modification History:
        !            26:  *
        !            27:  *       2/10/2000     Clark Warner    Added copyfile  
        !            28:  *       5/24/1999     Don Brady       Fixed security hole in get_fsvnode.
        !            29:  *      11/18/1998 Don Brady           Special case 2 to mean the root of a file system.
        !            30:  *       9/28/1998     Umesh Vaishampayan      Use the default vnode ops. Cleanup 
        !            31:  *                                                                     header includes.
        !            32:  *     11/12/1998      Scott Roberts   validfsnode only checks to see if the volfs mount flag is set
        !            33:  *       8/5/1998      Don Brady       fix validfsnode logic to handle a "bad" VFS_GET
        !            34:  *       7/5/1998      Don Brady       In volfs_reclaim set vp->v_data to NULL after private data is free (VFS expects a NULL).
        !            35:  *       4/5/1998      Don Brady       Changed lockstatus calls to VOP_ISLOCKED (radar #2231108);
        !            36:  *      3/25/1998      Pat Dirks       Added include for sys/attr.h, which is no longer included indirectly.
        !            37:  */
        !            38: 
        !            39: #include <mach/mach_types.h>
        !            40: 
        !            41: #include <sys/param.h>
        !            42: #include <sys/systm.h>
        !            43: #include <sys/resourcevar.h>
        !            44: #include <sys/kernel.h>
        !            45: #include <sys/file.h>
        !            46: #include <sys/stat.h>
        !            47: #include <sys/buf.h>
        !            48: #include <sys/proc.h>
        !            49: #include <sys/conf.h>
        !            50: #include <sys/mount.h>
        !            51: #include <sys/vnode.h>
        !            52: #include <sys/malloc.h>
        !            53: #include <sys/dirent.h>
        !            54: #include <sys/namei.h>
        !            55: #include <sys/attr.h>
        !            56: 
        !            57: #include <sys/vm.h>
        !            58: #include <sys/errno.h>
        !            59: #include <vfs/vfs_support.h>
        !            60: 
        !            61: #include "volfs.h"
        !            62: 
        !            63: /*
        !            64:  * volfs acts as a bridge between the requirements of the MacOS API and the Unix API.
        !            65:  * MacOS applications describe files by a <Volume ID><Directory ID><File Name> triple.
        !            66:  * The Unix API describes files by pathname.  Volfs is a virtual file system that sits over
        !            67:  * the HFS VFS interface and allows files to be described by a <Volume ID>/<Directory ID>/<File Name>
        !            68:  * pathname.
        !            69:  *
        !            70:  * The root of the volfs filesystem consists of directories named the volume ID's of all the
        !            71:  * currently mounted filesystems which support the VFS vget() routine.  Each of those directories
        !            72:  * supports the lookup by file ID of all files and directories within the filesystem.  When a
        !            73:  * file or directory is resolved its vnode from that filesystem rather than a volfs vnode is returned
        !            74:  * allowing immediate access to the target file or directory.
        !            75:  *
        !            76:  * Readdir on the root of the volfs filesystem returns the list of available file systems.  Readdir
        !            77:  * on a filesystem node, however, returns only . and .. since it is not practical to list all
        !            78:  * of the file ID's in a timely fashion and furthermore VFS does not provide a mechanism for
        !            79:  * enumerating all of the file id's.
        !            80:  *
        !            81:  * Volume ID's are taken from the low 32 bits of the f_fsid field, formatted as a base 10 ASCII
        !            82:  * string with no leading zeros (volume ID 1 is represented as "1").
        !            83:  *
        !            84:  * File ID's are created in same manner, with their 32 bits formatted as a base 10 ASCII
        !            85:  * string with no leading zeros.
        !            86:  *
        !            87:  * Volfs does create a security hole since it is possible to bypass directory permissions higher
        !            88:  * in the namespace tree.  This security hole is about the same as the one created by NFS which uses
        !            89:  * a similar mechanism.
        !            90:  */
        !            91: 
        !            92: /* Global vfs data structures for volfs. */
        !            93: int                 (**volfs_vnodeop_p) ();
        !            94: struct vnodeopv_entry_desc volfs_vnodeop_entries[] = {
        !            95:     {&vop_default_desc, vn_default_error},
        !            96:     {&vop_strategy_desc, err_strategy},        /* strategy */
        !            97:     {&vop_bwrite_desc, err_bwrite},            /* bwrite */
        !            98:     {&vop_lookup_desc, volfs_lookup},  /* lookup */
        !            99:     {&vop_create_desc, err_create},            /* create */
        !           100:     {&vop_whiteout_desc, err_whiteout},        /* whiteout */
        !           101:     {&vop_mknod_desc, err_mknod},              /* mknod */
        !           102:     {&vop_mkcomplex_desc, err_mkcomplex},      /* mkcomplex */
        !           103:     {&vop_open_desc, nop_open},                        /* open */
        !           104:     {&vop_close_desc, nop_close},              /* close */
        !           105:     {&vop_access_desc, volfs_access},  /* access */
        !           106:     {&vop_getattr_desc, volfs_getattr},        /* getattr */
        !           107:     {&vop_setattr_desc, err_setattr},  /* setattr */
        !           108:     {&vop_getattrlist_desc, err_getattrlist},  /* getattrlist */
        !           109:     {&vop_setattrlist_desc, err_setattrlist},  /* setattrlist */
        !           110:     {&vop_read_desc, err_read},                        /* read */
        !           111:     {&vop_write_desc, err_write},              /* write */
        !           112:     {&vop_lease_desc, err_lease},              /* lease */
        !           113:     {&vop_ioctl_desc, err_ioctl},              /* ioctl */
        !           114:     {&vop_select_desc, volfs_select},  /* select */
        !           115:     {&vop_exchange_desc, err_exchange},        /* exchange */
        !           116:     {&vop_revoke_desc, nop_revoke},            /* revoke */
        !           117:     {&vop_mmap_desc, err_mmap},                        /* mmap */
        !           118:     {&vop_fsync_desc, err_fsync},              /* fsync */
        !           119:     {&vop_seek_desc, nop_seek},                        /* seek */
        !           120:     {&vop_remove_desc, err_remove},            /* remove */
        !           121:     {&vop_link_desc, err_link},                        /* link */
        !           122:     {&vop_rename_desc, err_rename},            /* rename */
        !           123:     {&vop_mkdir_desc, err_mkdir},              /* mkdir */
        !           124:     {&vop_rmdir_desc, volfs_rmdir},            /* rmdir */
        !           125:     {&vop_symlink_desc, err_symlink},  /* symlink */
        !           126:     {&vop_readdir_desc, volfs_readdir},        /* readdir */
        !           127:     {&vop_readdirattr_desc, err_readdirattr},  /* readdirattr */
        !           128:     {&vop_readlink_desc, err_readlink},        /* readlink */
        !           129:     {&vop_abortop_desc, err_abortop},  /* abortop */
        !           130:     {&vop_inactive_desc, err_inactive},        /* inactive */
        !           131:     {&vop_reclaim_desc, volfs_reclaim},        /* reclaim */
        !           132:     {&vop_lock_desc, volfs_lock},              /* lock */
        !           133:     {&vop_unlock_desc, volfs_unlock},  /* unlock */
        !           134:     {&vop_bmap_desc, err_bmap},                        /* bmap */
        !           135:     {&vop_print_desc, err_print},              /* print */
        !           136:     {&vop_islocked_desc, volfs_islocked},      /* islocked */
        !           137:     {&vop_pathconf_desc, volfs_pathconf},      /* pathconf */
        !           138:     {&vop_advlock_desc, err_advlock},  /* advlock */
        !           139:     {&vop_blkatoff_desc, err_blkatoff},        /* blkatoff */
        !           140:     {&vop_valloc_desc, err_valloc},            /* valloc */
        !           141:     {&vop_reallocblks_desc, err_reallocblks},  /* reallocblks */
        !           142:     {&vop_vfree_desc, err_vfree},              /* vfree */
        !           143:     {&vop_truncate_desc, err_truncate},        /* truncate */
        !           144:     {&vop_allocate_desc, err_allocate},        /* allocate */
        !           145:     {&vop_update_desc, err_update},            /* update */
        !           146:        {&vop_pgrd_desc, err_pgrd},                     /* pgrd */
        !           147:        {&vop_pgwr_desc, err_pgwr},                     /* pgwr */
        !           148:        {&vop_pagein_desc, err_pagein},         /* pagein */
        !           149:        {&vop_pageout_desc, err_pageout},       /* pageout */
        !           150:        {&vop_devblocksize_desc, err_devblocksize},     /* devblocksize */
        !           151:        {&vop_searchfs_desc, err_searchfs},     /* searchfs */
        !           152:         {&vop_copyfile_desc, err_copyfile },                /* Copyfile */
        !           153:     {(struct vnodeop_desc *) NULL, (int (*) ()) NULL}
        !           154: };
        !           155: 
        !           156: /*
        !           157:  * Oh what a tangled web we weave.  This structure will be used by
        !           158:  * bsd/vfs/vfs_conf.c to actually do the initialization of volfs_vnodeop_p
        !           159:  */
        !           160: struct vnodeopv_desc volfs_vnodeop_opv_desc =
        !           161: {&volfs_vnodeop_p, volfs_vnodeop_entries};
        !           162: 
        !           163: 
        !           164: static int validfsnode(struct mount *fsnode);
        !           165: 
        !           166: #if DBG_VOP_TEST_LOCKS
        !           167: static void DbgVopTest (int max, int error, VopDbgStoreRec *VopDbgStore, char *funcname);
        !           168: #endif /* DBG_VOP_TEST_LOCKS */
        !           169: 
        !           170: 
        !           171: /*
        !           172:  * volfs_reclaim - Reclaim a vnode so that it can be used for other purposes.
        !           173:  *
        !           174:  * Locking policy: ignored
        !           175:  */
        !           176: int
        !           177: volfs_reclaim(ap)
        !           178:     struct vop_reclaim_args /* { struct vnode *a_vp; struct proc *a_p; } */ *ap;
        !           179: {
        !           180:     struct vnode *vp = ap->a_vp;
        !           181:     void *data = vp->v_data;
        !           182: 
        !           183:     DBG_FUNC_NAME("volfs_reclaim");
        !           184:     DBG_VOP_LOCKS_DECL(1);
        !           185:     DBG_VOP_PRINT_FUNCNAME();DBG_VOP_PRINT_VNODE_INFO(ap->a_vp);DBG_VOP(("\n"));
        !           186: 
        !           187:     DBG_VOP_LOCKS_INIT(0, vp, VOPDBG_UNLOCKED, VOPDBG_IGNORE, VOPDBG_IGNORE, VOPDBG_ZERO);
        !           188: 
        !           189:        vp->v_data = NULL;
        !           190:     FREE(data, M_VOLFSNODE);
        !           191: 
        !           192:     DBG_VOP_LOCKS_TEST(0);
        !           193:     return (0);
        !           194: }
        !           195: 
        !           196: /*
        !           197:  * volfs_access - same access policy for all vnodes and all users (file/directory vnodes
        !           198:  *             for the actual file systems are handled by actual file system)
        !           199:  *
        !           200:  * Locking policy: a_vp locked on input and output
        !           201:  */
        !           202: int
        !           203: volfs_access(ap)
        !           204:     struct vop_access_args     /* { struct vnode *a_vp; int  a_mode; struct
        !           205:         ucred *a_cred; struct proc *a_p; } */ *ap;
        !           206: {
        !           207:     int        ret_err;
        !           208:     DBG_FUNC_NAME("volfs_access");
        !           209:     DBG_VOP_LOCKS_DECL(1);
        !           210:     DBG_VOP_PRINT_FUNCNAME();DBG_VOP_PRINT_VNODE_INFO(ap->a_vp);DBG_VOP(("\n"));
        !           211: 
        !           212:     DBG_VOP_LOCKS_INIT(0,ap->a_vp, VOPDBG_LOCKED, VOPDBG_LOCKED, VOPDBG_LOCKED, VOPDBG_POS);
        !           213: 
        !           214:     /*
        !           215:      * We don't need to check credentials!  FS is read-only for everyone
        !           216:      */
        !           217:     if (ap->a_mode == VREAD || ap->a_mode == VEXEC)
        !           218:         ret_err = 0;
        !           219:     else
        !           220:         ret_err = EACCES;
        !           221: 
        !           222:     DBG_VOP_LOCKS_TEST(ret_err);
        !           223:     return (ret_err);
        !           224: }
        !           225: 
        !           226: /*
        !           227:  * volfs_getattr - fill in the attributes for this vnode
        !           228:  *
        !           229:  * Locking policy: don't change anything
        !           230:  */
        !           231: int
        !           232: volfs_getattr(ap)
        !           233:     struct vop_getattr_args    /* { struct vnode *a_vp; struct vattr *a_vap;
        !           234:         struct ucred *a_cred; struct proc *a_p; } */ *ap;
        !           235: {
        !           236:     struct volfs_vndata *priv_data;
        !           237:     struct vnode       *a_vp;
        !           238:     struct vattr       *a_vap;
        !           239:     int                 numMounts = 0;
        !           240:     DBG_FUNC_NAME("volfs_getattr");
        !           241:     DBG_VOP_LOCKS_DECL(1);
        !           242:     DBG_VOP_PRINT_FUNCNAME();DBG_VOP_PRINT_VNODE_INFO(ap->a_vp);DBG_VOP(("\n"));
        !           243: 
        !           244:     DBG_VOP_LOCKS_INIT(0,ap->a_vp, VOPDBG_SAME, VOPDBG_SAME, VOPDBG_SAME, VOPDBG_POS);
        !           245: 
        !           246:     a_vp = ap->a_vp;
        !           247:     a_vap = ap->a_vap;
        !           248: 
        !           249:     priv_data = a_vp->v_data;
        !           250: 
        !           251:     a_vap->va_type = VDIR;
        !           252:     a_vap->va_mode = 0444;     /* Yup, hard - coded to read - only */
        !           253:     a_vap->va_nlink = 2;
        !           254:     a_vap->va_uid = 0;         /* Always owned by root */
        !           255:     a_vap->va_gid = 0;         /* Always part of group 0 */
        !           256:     a_vap->va_fsid = (int) a_vp->v_mount->mnt_stat.f_fsid.val[0];
        !           257:     a_vap->va_fileid = priv_data->nodeID;
        !           258: 
        !           259:     /*
        !           260:      * If it's the root vnode calculate its size based on the number of eligible
        !           261:      * file systems
        !           262:      */
        !           263:     if (priv_data->vnode_type == VOLFS_ROOT)
        !           264:       {
        !           265:         register struct mount *mp, *nmp;
        !           266: 
        !           267:         simple_lock(&mountlist_slock);
        !           268:         for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
        !           269:             if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, ap->a_p)) {
        !           270:                 nmp = mp->mnt_list.cqe_next;
        !           271:                 continue;
        !           272:             }
        !           273: 
        !           274:             if (mp != a_vp->v_mount && validfsnode(mp))
        !           275:                 numMounts++;
        !           276: 
        !           277:             simple_lock(&mountlist_slock);
        !           278:             nmp = mp->mnt_list.cqe_next;
        !           279:             vfs_unbusy(mp, ap->a_p);
        !           280:         }
        !           281:         simple_unlock(&mountlist_slock);
        !           282: 
        !           283:         DBG_VOP(("found %d file systems that volfs can support\n", numMounts));
        !           284:         a_vap->va_size = (numMounts + 2) * VLFSDIRENTLEN;
        !           285:       }
        !           286:     else
        !           287:       {
        !           288:         a_vap->va_size = 2 * VLFSDIRENTLEN;
        !           289:       }
        !           290:     DBG_VOP(("va_size = %d, VLFSDIRENTLEN = %ld\n", (int) a_vap->va_size, VLFSDIRENTLEN));
        !           291:     a_vap->va_blocksize = 512;
        !           292: 
        !           293:     a_vap->va_atime.tv_sec = boottime.tv_sec;
        !           294:     a_vap->va_atime.tv_nsec = 0;
        !           295: 
        !           296:     a_vap->va_mtime.tv_sec = boottime.tv_sec;
        !           297:     a_vap->va_mtime.tv_nsec = 0;
        !           298: 
        !           299:     a_vap->va_ctime.tv_sec = boottime.tv_sec;
        !           300:     a_vap->va_ctime.tv_nsec = 0;
        !           301: 
        !           302:     a_vap->va_gen = 0;
        !           303:     a_vap->va_flags = 0;
        !           304:     a_vap->va_rdev = 0;
        !           305:     a_vap->va_bytes = a_vap->va_size;
        !           306:     a_vap->va_filerev = 0;
        !           307:     a_vap->va_vaflags = 0;
        !           308: 
        !           309:     DBG_VOP_LOCKS_TEST(0);
        !           310:     return (0);
        !           311: }
        !           312: 
        !           313: /*
        !           314:  * volfs_select - just say OK.  Only possible op is readdir
        !           315:  *
        !           316:  * Locking policy: ignore
        !           317:  */
        !           318: int
        !           319: volfs_select(ap)
        !           320:     struct vop_select_args     /* { struct vnode *a_vp; int  a_which; int
        !           321:                                 * a_fflags; struct ucred *a_cred; struct
        !           322:         proc *a_p; } */ *ap;
        !           323: {
        !           324:     DBG_VOP(("volfs_select called\n"));
        !           325: 
        !           326:     return (1);
        !           327: }
        !           328: 
        !           329: /*
        !           330:  * vofls_rmdir - not possible to remove directories in volfs
        !           331:  *
        !           332:  * Locking policy: a_dvp & a_vp - locked on entry, unlocked on exit
        !           333:  */
        !           334: int
        !           335: volfs_rmdir(ap)
        !           336:     struct vop_rmdir_args      /* { struct vnode *a_dvp; struct vnode *a_vp;
        !           337:         struct componentname *a_cnp; } */ *ap;
        !           338: {
        !           339:     DBG_VOP(("volfs_rmdir called\n"));
        !           340:     if (ap->a_dvp == ap->a_vp) {
        !           341:                (void) nop_rmdir(ap);
        !           342:                return (EINVAL);
        !           343:     } else
        !           344:                return (err_rmdir(ap));
        !           345: }
        !           346: 
        !           347: /*
        !           348:  * volfs_readdir - Get directory entries
        !           349:  *
        !           350:  * Directory listings are only produced for the root volfs node.  Filesystems
        !           351:  * just return . & ..
        !           352:  * Filesystems contained within the volfs root are named by the decimal
        !           353:  * equivalent of the f_fsid.val[0] from their mount structure (typically
        !           354:  * the device id of the volume).  The maximum length for a name, then is
        !           355:  * 10 characters.
        !           356:  *
        !           357:  * Locking policy: a_vp locked on entry and exit
        !           358:  */
        !           359: int
        !           360: volfs_readdir(ap)
        !           361:     struct vop_readdir_args    /* { struct vnode *a_vp; struct uio *a_uio;
        !           362:                                 * struct ucred *a_cred; int *a_eofflag; int
        !           363:         *ncookies; u_long **a_cookies; } */ *ap;
        !           364: {
        !           365:     struct volfs_vndata *priv_data;
        !           366:     register struct uio *uio = ap->a_uio;
        !           367:     int                 error = 0;
        !           368:     size_t              count, lost;
        !           369:     int                 rec_offset;
        !           370:     struct dirent       local_dir;
        !           371:     int                 i;
        !           372:     int                                        starting_resid;
        !           373:     off_t               off;
        !           374:     DBG_FUNC_NAME("volfs_readdir");
        !           375:     DBG_VOP_LOCKS_DECL(1);
        !           376: 
        !           377:     DBG_VOP_LOCKS_INIT(0,ap->a_vp, VOPDBG_LOCKED, VOPDBG_LOCKED, VOPDBG_LOCKED, VOPDBG_POS);
        !           378:     DBG_VOP_PRINT_FUNCNAME();DBG_VOP_PRINT_VNODE_INFO(ap->a_vp);DBG_VOP(("\n"));
        !           379: 
        !           380:     DBG_VOP(("\tuio_offset = %d, uio_resid = %d\n", (int) uio->uio_offset, uio->uio_resid));
        !           381:        /* We assume it's all one big buffer... */
        !           382:     if (uio->uio_iovcnt > 1)
        !           383:        DBG_VOP(("\tuio->uio_iovcnt = %d?\n", uio->uio_iovcnt));
        !           384: 
        !           385:        off = uio->uio_offset;
        !           386:     priv_data = ap->a_vp->v_data;
        !           387:     starting_resid = uio->uio_resid;
        !           388:     count = uio->uio_resid;
        !           389:  
        !           390:     /* Make sure we don't return partial entries. */
        !           391:     count -= (uio->uio_offset + count) & (VLFSDIRENTLEN - 1);
        !           392:     if (count <= 0)
        !           393:                {
        !           394:         DBG_VOP(("volfs_readdir: Not enough buffer to read in entries\n"));
        !           395:         DBG_VOP_LOCKS_TEST(EINVAL);
        !           396:         return (EINVAL);
        !           397:                }
        !           398:     /*
        !           399:      * Make sure we're starting on a directory boundary
        !           400:      */
        !           401:     if (off & (VLFSDIRENTLEN - 1))
        !           402:         {
        !           403:         DBG_VOP_LOCKS_TEST(EINVAL);
        !           404:         return (EINVAL);
        !           405:         }
        !           406:     rec_offset = off / VLFSDIRENTLEN;
        !           407:     lost = uio->uio_resid - count;
        !           408:     uio->uio_resid = count;
        !           409:     uio->uio_iov->iov_len = count;
        !           410: 
        !           411:     local_dir.d_reclen = VLFSDIRENTLEN;
        !           412:     /*
        !           413:      * We must synthesize . and ..
        !           414:      */
        !           415:     DBG_VOP(("\tstarting ... uio_offset = %d, uio_resid = %d\n",
        !           416:             (int) uio->uio_offset, uio->uio_resid));
        !           417:     if (rec_offset == 0)
        !           418:       {
        !           419:         DBG_VOP(("\tAdding .\n"));
        !           420:         /*
        !           421:          * Synthesize .
        !           422:          */
        !           423:         local_dir.d_fileno = priv_data->nodeID;
        !           424:         local_dir.d_type = DT_DIR;
        !           425:         local_dir.d_namlen = 1;
        !           426:         local_dir.d_name[0] = '.';
        !           427:         for (i = 1; i < MAXVLFSNAMLEN; i++)
        !           428:             local_dir.d_name[i] = 0;
        !           429:         error = uiomove((char *) &local_dir, VLFSDIRENTLEN, uio);
        !           430:         DBG_VOP(("\t   after adding ., uio_offset = %d, uio_resid = %d\n",
        !           431:                 (int) uio->uio_offset, uio->uio_resid));
        !           432:         rec_offset++;
        !           433:       }
        !           434:     if (rec_offset == 1)
        !           435:       {
        !           436:         DBG_VOP(("\tAdding ..\n"));
        !           437:         /*
        !           438:          * Synthesize ..
        !           439:          * We only have two levels in the volfs hierarchy.  Root's
        !           440:          * .. points to itself and the second level points to root,
        !           441:          * hence we've hardcoded d_fileno for .. here
        !           442:          */
        !           443:         local_dir.d_fileno = ROOT_DIRID;
        !           444:         local_dir.d_type = DT_DIR;
        !           445:         local_dir.d_namlen = 2;
        !           446:         local_dir.d_name[0] = '.';
        !           447:         local_dir.d_name[1] = '.';
        !           448:         for (i = 2; i < MAXVLFSNAMLEN; i++)
        !           449:             local_dir.d_name[i] = 0;
        !           450:         error = uiomove((char *) &local_dir, VLFSDIRENTLEN, uio);
        !           451:         rec_offset++;
        !           452:         DBG_VOP(("\t   after adding .., uio_offset = %d, uio_resid = %d\n",
        !           453:                 (int) uio->uio_offset, uio->uio_resid));
        !           454:       }
        !           455: 
        !           456:     /*
        !           457:      * OK, we've given them the . & .. entries.  If this is a
        !           458:      * filesystem node then we've gone as far as we're going
        !           459:      * to go
        !           460:      */
        !           461:     if (priv_data->vnode_type == VOLFS_FSNODE)
        !           462:         {
        !           463:         *ap->a_eofflag = 1;    /* we got all the way to the end */
        !           464:         DBG_VOP_LOCKS_TEST(error);
        !           465:         return (error);
        !           466:         }
        !           467: 
        !           468:     if (rec_offset > 1) {
        !           469:         register struct mount *mp, *nmp;
        !           470:         int                                    validnodeindex;
        !           471:         struct proc            *p = uio->uio_procp;
        !           472: 
        !           473:         validnodeindex = 1;    /* we always have "." and ".." */
        !           474: 
        !           475:         simple_lock(&mountlist_slock);
        !           476:         for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
        !           477:             if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
        !           478:                 nmp = mp->mnt_list.cqe_next;
        !           479:                 continue;
        !           480:             }
        !           481: 
        !           482:             if (mp != ap->a_vp->v_mount && validfsnode(mp))
        !           483:                 validnodeindex++;
        !           484: 
        !           485:             if (rec_offset == validnodeindex)
        !           486:               {
        !           487:                 local_dir.d_fileno = mp->mnt_stat.f_fsid.val[0];
        !           488:                 local_dir.d_type = DT_DIR;
        !           489:                 local_dir.d_reclen = VLFSDIRENTLEN;
        !           490:                 DBG_VOP(("\tAdding dir entry %d for offset %d\n", mp->mnt_stat.f_fsid.val[0], rec_offset));
        !           491:                 local_dir.d_namlen = sprintf(&local_dir.d_name[0], "%d",
        !           492:                        (mp->mnt_flag & MNT_ROMANONLY) ? mp->mnt_stat.f_fsid.val[0] | VOLFS_ROMANONLY : mp->mnt_stat.f_fsid.val[0] );
        !           493: 
        !           494:                 error = uiomove((char *) &local_dir, VLFSDIRENTLEN, uio);
        !           495:                 DBG_VOP(("\t   after adding entry '%s', uio_offset = %d, uio_resid = %d\n",
        !           496:                          &local_dir.d_name[0], (int) uio->uio_offset, uio->uio_resid));
        !           497:                 rec_offset++;
        !           498:               }
        !           499: 
        !           500:             simple_lock(&mountlist_slock);
        !           501:             nmp = mp->mnt_list.cqe_next;
        !           502:             vfs_unbusy(mp, p);
        !           503:         }
        !           504:         simple_unlock(&mountlist_slock);
        !           505: 
        !           506:         if (mp == (void *) &mountlist)
        !           507:             *ap->a_eofflag = 1;        /* we got all the way to the end */
        !           508:     }
        !           509: 
        !           510:     uio->uio_resid += lost;
        !           511:     if (starting_resid == uio->uio_resid)
        !           512:         uio->uio_offset = 0;
        !           513: 
        !           514:     DBG_VOP(("\tExiting, uio_offset = %d, uio_resid = %d, ap->a_eofflag = %d\n",
        !           515:             (int) uio->uio_offset, uio->uio_resid, *ap->a_eofflag));
        !           516: 
        !           517:     DBG_VOP_LOCKS_TEST(error);
        !           518:     return (error);
        !           519: }
        !           520: 
        !           521: 
        !           522: /*
        !           523:  * validfsnode - test to see if a file system supports VGET
        !           524:  *
        !           525:  * This can cause context switching, so caller should be lock safe
        !           526:  */
        !           527: static int
        !           528: validfsnode(struct mount *fsnode)
        !           529: {
        !           530: 
        !           531:        /*
        !           532:         * Just check to see if the the mount flag is set, if it is we assume the
        !           533:         * file system supports all of volfs symantecs
        !           534:         */
        !           535: 
        !           536:     if (fsnode->mnt_flag & MNT_DOVOLFS)
        !           537:                return 1;
        !           538:        else 
        !           539:                return 0;
        !           540: }
        !           541: 
        !           542: /*
        !           543:  * volfs_lock - Lock an inode.
        !           544:  * If its already locked, set the WANT bit and sleep.
        !           545:  *
        !           546:  * Locking policy: handled by lockmgr
        !           547:  */
        !           548: int
        !           549: volfs_lock(ap)
        !           550:     struct vop_lock_args       /* { struct vnode *a_vp; int a_flags; struct
        !           551:         proc *a_p; } */ *ap;
        !           552: {
        !           553:     int                 retval;
        !           554:     struct volfs_vndata *priv_data;
        !           555:     DBG_FUNC_NAME("volfs_lock");
        !           556:     DBG_VOP_LOCKS_DECL(1);
        !           557:     DBG_VOP_PRINT_FUNCNAME();DBG_VOP_PRINT_VNODE_INFO(ap->a_vp);DBG_VOP(("\n"));
        !           558: 
        !           559:     DBG_VOP_LOCKS_INIT(0,ap->a_vp, VOPDBG_UNLOCKED, VOPDBG_LOCKED, VOPDBG_UNLOCKED, VOPDBG_ZERO);
        !           560: 
        !           561:     priv_data = (struct volfs_vndata *) ap->a_vp->v_data;
        !           562:     retval = lockmgr(&priv_data->lock, ap->a_flags, &ap->a_vp->v_interlock, ap->a_p);
        !           563:     DBG_VOP_LOCKS_TEST(retval);
        !           564:     return (retval);
        !           565: }
        !           566: 
        !           567: /*
        !           568:  * volfs_unlock - Unlock an inode.
        !           569:  *
        !           570:  * Locking policy: handled by lockmgr
        !           571:  */
        !           572: int
        !           573: volfs_unlock(ap)
        !           574:     struct vop_unlock_args     /* { struct vnode *a_vp; int a_flags; struct
        !           575:         proc *a_p; } */ *ap;
        !           576: {
        !           577:     int                 retval;
        !           578:     struct volfs_vndata *priv_data;
        !           579:     DBG_FUNC_NAME("volfs_unlock");
        !           580:     DBG_VOP_LOCKS_DECL(1);
        !           581:     DBG_VOP_PRINT_FUNCNAME();DBG_VOP_PRINT_VNODE_INFO(ap->a_vp);DBG_VOP(("\n"));
        !           582: 
        !           583:     DBG_VOP_LOCKS_INIT(0,ap->a_vp, VOPDBG_LOCKED, VOPDBG_UNLOCKED, VOPDBG_LOCKED, VOPDBG_ZERO);
        !           584: 
        !           585:     priv_data = (struct volfs_vndata *) ap->a_vp->v_data;
        !           586:     retval = lockmgr(&priv_data->lock, ap->a_flags | LK_RELEASE,
        !           587:                     &ap->a_vp->v_interlock, ap->a_p);
        !           588: 
        !           589:     DBG_VOP_LOCKS_TEST(retval);
        !           590:     return (retval);
        !           591: }
        !           592: 
        !           593: /*
        !           594:  * volfs_islocked - Check for a locked inode.
        !           595:  *
        !           596:  * Locking policy: ignore
        !           597:  */
        !           598: int
        !           599: volfs_islocked(ap)
        !           600:     struct vop_islocked_args /* { struct vnode *a_vp; } */ *ap;
        !           601: {
        !           602:     int                 retval;
        !           603:     struct volfs_vndata *priv_data;
        !           604: 
        !           605:     DBG_FUNC_NAME("volfs_islocked");
        !           606:     DBG_VOP_LOCKS_DECL(1);
        !           607:     //DBG_VOP_PRINT_FUNCNAME();DBG_VOP(("\n"));
        !           608: 
        !           609:     DBG_VOP_LOCKS_INIT(0,ap->a_vp, VOPDBG_IGNORE, VOPDBG_IGNORE, VOPDBG_IGNORE, VOPDBG_ZERO);
        !           610:     priv_data = (struct volfs_vndata *) ap->a_vp->v_data;
        !           611:     retval = lockstatus(&priv_data->lock);
        !           612: 
        !           613:     DBG_VOP_LOCKS_TEST(retval);
        !           614:     return (retval);
        !           615: }
        !           616: 
        !           617: /*
        !           618:  * volfs_pathconf - Return POSIX pathconf information applicable to ufs filesystems.
        !           619:  *
        !           620:  * Locking policy: a_vp locked on input and output
        !           621:  */
        !           622: int
        !           623: volfs_pathconf(ap)
        !           624:     struct vop_pathconf_args   /* { struct vnode *a_vp; int a_name; int
        !           625:         *a_retval; } */ *ap;
        !           626: {
        !           627:     DBG_VOP(("volfs_pathconf called\n"));
        !           628: 
        !           629:     switch (ap->a_name)
        !           630:       {
        !           631:         case _PC_LINK_MAX:
        !           632:             *ap->a_retval = LINK_MAX;
        !           633:             return (0);
        !           634:         case _PC_NAME_MAX:
        !           635:             *ap->a_retval = NAME_MAX;
        !           636:             return (0);
        !           637:         case _PC_PATH_MAX:
        !           638:             *ap->a_retval = PATH_MAX;
        !           639:             return (0);
        !           640:         case _PC_PIPE_BUF:
        !           641:             *ap->a_retval = PIPE_BUF;
        !           642:             return (0);
        !           643:         case _PC_CHOWN_RESTRICTED:
        !           644:             *ap->a_retval = 1;
        !           645:             return (0);
        !           646:         case _PC_NO_TRUNC:
        !           647:             *ap->a_retval = 1;
        !           648:             return (0);
        !           649:         default:
        !           650:             return (EINVAL);
        !           651:       }
        !           652:     /* NOTREACHED */
        !           653: }
        !           654: 
        !           655: /*
        !           656:  * get_fsvnode - internal routine to create a vnode for a file system.  Called with mount pointer,
        !           657:  *   id of filesystem to lookup and pointer to vnode pointer to fill in
        !           658:  */
        !           659: static int
        !           660: get_fsvnode(our_mount, id, ret_vnode)
        !           661:     struct mount       *our_mount;
        !           662:     int id;
        !           663:     struct vnode      **ret_vnode;
        !           664: {
        !           665:     register struct mount *mp;
        !           666:     struct mount       *cur_mount;
        !           667:     struct vnode       *cur_vnode;
        !           668:     struct volfs_vndata *cur_privdata;
        !           669:        int                                     retval;
        !           670: 
        !           671:     //DBG_VOP(("volfs: get_fsvnode called\n"));
        !           672: 
        !           673:     /*
        !           674:      * OK, first look up the matching mount on the list of mounted file systems
        !           675:      */
        !           676:     cur_mount = NULL;
        !           677:     simple_lock(&mountlist_slock);
        !           678:     for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = mp->mnt_list.cqe_next)
        !           679:       {
        !           680:         if (validfsnode(mp) && mp->mnt_stat.f_fsid.val[0] == id)
        !           681:           {
        !           682:             cur_mount = mp;
        !           683:             break;
        !           684:           }
        !           685:       }
        !           686:     simple_unlock(&mountlist_slock);
        !           687: 
        !           688:     if (cur_mount == NULL) {
        !           689:         /*
        !           690:          * No mounted file system by the specified ID currently exists in the system.
        !           691:          *
        !           692:          * XXX We could deal with a vnode that is still hanging about for an FS that
        !           693:          * does not exists or has been unmounted now, or count on the update below
        !           694:          * to happen later...
        !           695:          */
        !           696:         *ret_vnode = NULL;
        !           697:         return ENOENT;
        !           698:     };
        !           699: 
        !           700:     /*
        !           701:      * Now search the list attached to the mount structure to
        !           702:      * see if this vnode is already floating around
        !           703:      */
        !           704: search_vnodelist:
        !           705:     cur_vnode = our_mount->mnt_vnodelist.lh_first;
        !           706:     while (cur_vnode != NULL)
        !           707:       {
        !           708:         cur_privdata = (struct volfs_vndata *) cur_vnode->v_data;
        !           709:         if (cur_privdata->nodeID == id)
        !           710:             {
        !           711:             if (cur_privdata->fs_mount != cur_mount) {
        !           712:                 DBG_VOP(("volfs get_fsvnode: Updating fs_mount for vnode 0x%08lX (id = %d) from 0x%08lX to 0x%08lX...\n",
        !           713:                          (unsigned long)cur_vnode,
        !           714:                          cur_privdata->nodeID,
        !           715:                          (unsigned long)cur_privdata->fs_mount,
        !           716:                          (unsigned long)cur_mount));
        !           717:                 cur_privdata->fs_mount = cur_mount;
        !           718:             };
        !           719:             break;
        !           720:             }
        !           721:         cur_vnode = cur_vnode->v_mntvnodes.le_next;
        !           722:       }
        !           723: 
        !           724:     //DBG_VOP(("\tfinal cur_mount: 0x%x\n",cur_mount));
        !           725:     if (cur_vnode) {
        !           726:         /* If vget returns an error, cur_vnode will not be what we think it is, try again */
        !           727:         if (vget(cur_vnode, LK_EXCLUSIVE, current_proc()) != 0) {
        !           728:             goto search_vnodelist;
        !           729:         };
        !           730:         }
        !           731:     else
        !           732:       {
        !           733:         MALLOC(cur_privdata, struct volfs_vndata *,
        !           734:                sizeof(struct volfs_vndata), M_VOLFSNODE, M_WAITOK);
        !           735:         retval = getnewvnode(VT_VOLFS, our_mount, volfs_vnodeop_p, &cur_vnode);
        !           736:         if (retval != 0) {
        !           737:             FREE(cur_privdata, M_VOLFSNODE);
        !           738:             return retval;
        !           739:         };
        !           740:                        
        !           741:         cur_privdata->vnode_type = VOLFS_FSNODE;
        !           742:         cur_privdata->nodeID = id;
        !           743: 
        !           744:         cur_privdata->fs_mount = cur_mount;
        !           745:         lockinit(&cur_privdata->lock, PINOD, "volfsnode", 0, 0);
        !           746:         lockmgr(&cur_privdata->lock, LK_EXCLUSIVE, (struct slock *)0, current_proc());
        !           747:         cur_vnode->v_data = cur_privdata;
        !           748:         cur_vnode->v_type = VDIR;
        !           749:         DBG_VOP(("get_fsvnode returned with new node of "));
        !           750:         DBG_VOP_PRINT_VNODE_INFO(cur_vnode);DBG_VOP(("\n"));
        !           751:       }
        !           752: 
        !           753:     *ret_vnode = cur_vnode;
        !           754: 
        !           755:     return (0);
        !           756: }
        !           757: 
        !           758: 
        !           759: 
        !           760: /*
        !           761:  * get_filevnode - returns the vnode for the given id within a filesystem.  The parent vnode
        !           762:  *        is a filesystem, id is the 32-bit id of the file/directory and ret_vnode is a pointer
        !           763:  *             to a vnode pointer
        !           764:  */
        !           765: static int
        !           766: get_filevnode(parent_fs, id, ret_vnode)
        !           767:     struct mount       *parent_fs;
        !           768:     u_int                              id;
        !           769:     struct vnode       **ret_vnode;
        !           770: {
        !           771:     int                 retval;
        !           772: 
        !           773:     DBG_VOP(("get_filevnode called for ID %d\n", id));
        !           774: 
        !           775:        /*
        !           776:         * Special case 2 to mean the root of a file system
        !           777:         */
        !           778:        if (id == 2)
        !           779:                retval = VFS_ROOT(parent_fs, ret_vnode);
        !           780:        else
        !           781:        retval = VFS_VGET(parent_fs, &id, ret_vnode);
        !           782: 
        !           783:     return (retval);
        !           784: }
        !           785: 
        !           786: 
        !           787: int
        !           788: volfs_lookup(ap)
        !           789:     struct vop_lookup_args     /* { struct vnode *a_dvp; struct vnode
        !           790:         **a_vpp; struct componentname *a_cnp; } */ *ap;
        !           791: {
        !           792:     struct volfs_vndata *priv_data;
        !           793:     char                               *cnp;
        !           794:     long                               namelen;
        !           795:     struct mount               *parent_fs;
        !           796:     int                                        unlocked_parent = 0;
        !           797:     int                 ret_err = ENOENT;
        !           798:     DBG_FUNC_NAME("volfs_lookup");
        !           799:     DBG_VOP_LOCKS_DECL(2);
        !           800: 
        !           801:     DBG_VOP(("volfs_lookup called, name = %s, namelen = %ld\n", ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
        !           802: 
        !           803:     DBG_VOP_LOCKS_INIT(0,ap->a_dvp, VOPDBG_LOCKED, VOPDBG_IGNORE, VOPDBG_IGNORE, VOPDBG_POS);
        !           804:     DBG_VOP_LOCKS_INIT(1,*ap->a_vpp, VOPDBG_IGNORE, VOPDBG_LOCKED, VOPDBG_IGNORE, VOPDBG_POS);
        !           805:     DBG_VOP_PRINT_FUNCNAME();DBG_VOP(("\n"));
        !           806:     DBG_VOP(("\t"));DBG_VOP_PRINT_CPN_INFO(ap->a_cnp);DBG_VOP(("\n"));
        !           807:        if (ap->a_cnp->cn_flags & LOCKPARENT)
        !           808:                DBG_VOP(("\tLOCKPARENT is set\n"));
        !           809:        if (ap->a_cnp->cn_flags & ISLASTCN)
        !           810:                {
        !           811:                DBG_VOP(("\tISLASTCN is set\n"));
        !           812:                if (ap->a_cnp->cn_nameiop == DELETE || ap->a_cnp->cn_nameiop == RENAME)         /* XXX PPD Shouldn't we check for CREATE, too? */
        !           813:                        {
        !           814:                        ret_err = EROFS;
        !           815:                        goto Err_Exit;
        !           816:                        }
        !           817:                }
        !           818:        priv_data = ap->a_dvp->v_data;
        !           819:        cnp = ap->a_cnp->cn_nameptr;
        !           820:        namelen = ap->a_cnp->cn_namelen;
        !           821:        
        !           822: #if VOLFS_DEBUG
        !           823:     switch (priv_data->vnode_type) {
        !           824:         case VOLFS_ROOT:
        !           825:             DBG_VOP(("\tparent directory (vnode 0x%08lX) vnode_type is VOLFS_ROOT.\n", (unsigned long)ap->a_dvp));
        !           826:             break;
        !           827: 
        !           828:         case VOLFS_FSNODE:
        !           829:             DBG_VOP(("\tparent directory (vnode 0x%08lX) vnode_type is VOLFS_FSNODE, nodeID = %d, fs_mount = 0x%08lX.\n",
        !           830:                      (unsigned long)ap->a_dvp,
        !           831:                      priv_data->nodeID,
        !           832:                      (unsigned long)priv_data->fs_mount));
        !           833: 
        !           834:         default:
        !           835:             DBG_VOP(("\tparent directory (vnode 0x%08lX) has unknown vnode_type (%d), nodeID = %d.\n",
        !           836:                      (unsigned long)ap->a_dvp,
        !           837:                      priv_data->vnode_type,
        !           838:                      priv_data->nodeID));
        !           839:     };
        !           840: #endif /* VOLFS_DEBUG */
        !           841: 
        !           842:        /* first check for "." and ".." */
        !           843:        if (cnp[0] == '.')
        !           844:        {
        !           845:                if (namelen == 1)
        !           846:                {
        !           847:                        /* "." requested */
        !           848:                    *ap->a_vpp = ap->a_dvp;
        !           849:                    VREF(*ap->a_vpp);
        !           850:             DBG_VOP_LOCKS_TEST(0);
        !           851:             return (0);
        !           852:                }
        !           853:                else if (cnp[1] == '.' && namelen == 2) 
        !           854:                {
        !           855:                        /* ".." requested */
        !           856:                        ret_err = volfs_root(ap->a_dvp->v_mount, ap->a_vpp);
        !           857:                }
        !           858:        }
        !           859: 
        !           860:        /* then look for special file system root symbol ('@') */
        !           861:        else if (cnp[0] == '@')
        !           862:        {
        !           863:                if ((namelen == 1) && (priv_data->vnode_type != VOLFS_ROOT)) {
        !           864:                        parent_fs = priv_data->fs_mount;
        !           865:                        if (!(ap->a_cnp->cn_flags & LOCKPARENT) || !(ap->a_cnp->cn_flags & ISLASTCN)) {
        !           866:                                VOP_UNLOCK(ap->a_dvp, 0, ap->a_cnp->cn_proc);
        !           867:                                unlocked_parent = 1;
        !           868:                        };
        !           869:                        ret_err = VFS_ROOT(parent_fs, ap->a_vpp);
        !           870:         } else {
        !           871:             DBG_VOP(("volfs_lookup: pathname = '@' but namelen = %ld and parent vnode_type = %d.\n", namelen, priv_data->vnode_type));
        !           872:             *ap->a_vpp = NULL;
        !           873:             ret_err = ENOENT;
        !           874:         };
        !           875:        }
        !           876: 
        !           877:        /* finally, just look for numeric ids... */
        !           878:        else if (namelen <= 10 && cnp[0] > '0' && cnp[0] <= '9') /* 10 digits max lead digit must be 1 - 9 */
        !           879:        {
        !           880:                char    *check_ptr;
        !           881:                u_long  id;
        !           882: 
        !           883:                id = strtol(cnp, &check_ptr, 10);
        !           884: 
        !           885:        /*
        !           886:                 * strtol will leave us at the first non-numeric character.
        !           887:                 * we've checked to make sure the component name does
        !           888:                 * begin with a numeric so check_ptr must wind up on
        !           889:                 * the terminating null or there was other junk following the
        !           890:                 * number
        !           891:                 */
        !           892:                if ((check_ptr - cnp) == namelen)
        !           893:                {
        !           894:                    if (priv_data->vnode_type == VOLFS_ROOT)
        !           895:                                ret_err = get_fsvnode(ap->a_dvp->v_mount, id & ~VOLFS_VOLIDFLAGS, ap->a_vpp);
        !           896:                    else {
        !           897:                        parent_fs = priv_data->fs_mount;
        !           898:                                if (!(ap->a_cnp->cn_flags & LOCKPARENT) || !(ap->a_cnp->cn_flags & ISLASTCN)) {
        !           899:                                        VOP_UNLOCK(ap->a_dvp, 0, ap->a_cnp->cn_proc);
        !           900:                                        unlocked_parent = 1;
        !           901:                                };
        !           902:                                ret_err = get_filevnode(parent_fs, id, ap->a_vpp);
        !           903:                        }
        !           904:                }
        !           905: 
        !           906:        }
        !           907: 
        !           908:        if (!unlocked_parent && (!(ap->a_cnp->cn_flags & LOCKPARENT) || !(ap->a_cnp->cn_flags & ISLASTCN))) {
        !           909:                VOP_UNLOCK(ap->a_dvp, 0, ap->a_cnp->cn_proc);
        !           910:        };
        !           911: 
        !           912:        /* XXX PPD Should we do something special in case LOCKLEAF isn't set? */
        !           913: 
        !           914: Err_Exit:
        !           915: 
        !           916:        DBG_VOP_UPDATE_VP(1, *ap->a_vpp);
        !           917:        DBG_VOP_LOCKS_TEST(ret_err);
        !           918:     
        !           919:     return (ret_err);
        !           920: }
        !           921: 
        !           922: #if DBG_VOP_TEST_LOCKS
        !           923: 
        !           924: #if 0
        !           925: static void DbgLookupTest(     char *funcname, struct componentname  *cnp, struct vnode *dvp, struct vnode *vp)
        !           926: {
        !           927:     int                flags = cnp->cn_flags;
        !           928:     int                nameiop = cnp->cn_nameiop;
        !           929: 
        !           930:     DBG_VOP (("%s: Action:", funcname));
        !           931:     switch (nameiop)
        !           932:         {
        !           933:         case LOOKUP:
        !           934:             PRINTIT ("LOOKUP");
        !           935:             break;
        !           936:         case CREATE:
        !           937:             PRINTIT ("CREATE");
        !           938:             break;
        !           939:         case DELETE:
        !           940:             PRINTIT ("DELETE");
        !           941:             break;
        !           942:         case RENAME:
        !           943:             PRINTIT ("RENAME");
        !           944:             break;
        !           945:         default:
        !           946:             PRINTIT ("!!!UNKNOWN!!!!");
        !           947:             break;
        !           948:             }
        !           949:     PRINTIT(" flags: 0x%x ",flags );
        !           950:     if (flags & LOCKPARENT)
        !           951:         PRINTIT (" Lock Parent");
        !           952:     if (flags & ISLASTCN)
        !           953:         PRINTIT (" Last Action");
        !           954:     PRINTIT("\n");
        !           955: 
        !           956:     if (dvp)
        !           957:         {
        !           958:         PRINTIT ("%s: Parent vnode exited ", funcname);
        !           959:     if (VOP_ISLOCKED(dvp))
        !           960:             PRINTIT("LOCKED\n");
        !           961:         else
        !           962:             PRINTIT("UNLOCKED\n");
        !           963:         }
        !           964:     if (vp && vp==dvp)
        !           965:         {
        !           966:         PRINTIT ("%s: Found and Parent are the same\n", funcname);
        !           967:         }
        !           968:     else if (vp)
        !           969:         {
        !           970:         PRINTIT ("%s: Found vnode exited ", funcname);
        !           971:     if (VOP_ISLOCKED(vp))
        !           972:             PRINTIT("LOCKED\n");
        !           973:         else
        !           974:             PRINTIT("UNLOCKED\n");
        !           975:         }
        !           976:     else
        !           977:         PRINTIT ("%s: Found vnode exited NULL\n", funcname);
        !           978: 
        !           979: 
        !           980: }
        !           981: #endif
        !           982: 
        !           983: static void DbgVopTest( int maxSlots,
        !           984:                  int retval,
        !           985:                  VopDbgStoreRec *VopDbgStore,
        !           986:                  char *funcname)
        !           987: {
        !           988:     int index;
        !           989: 
        !           990:     for (index = 0; index < maxSlots; index++)
        !           991:       {
        !           992:         if (VopDbgStore[index].id != index) {
        !           993:             PRINTIT("%s: DBG_VOP_LOCK: invalid id field (%d) in target entry (#%d).\n", funcname, VopDbgStore[index].id, index);
        !           994:                return;
        !           995:         };
        !           996: 
        !           997:         if ((VopDbgStore[index].vp != NULL) &&
        !           998:             ((VopDbgStore[index].vp->v_data==NULL)))
        !           999:             continue;
        !          1000: 
        !          1001:         switch (VopDbgStore[index].inState)
        !          1002:           {
        !          1003:             case VOPDBG_IGNORE:
        !          1004:             case VOPDBG_SAME:
        !          1005:                 /* Do Nothing !!! */
        !          1006:                 break;
        !          1007:             case VOPDBG_LOCKED:
        !          1008:             case VOPDBG_UNLOCKED:
        !          1009:             case VOPDBG_LOCKNOTNIL:
        !          1010:               {
        !          1011:                   if (VopDbgStore[index].vp == NULL && (VopDbgStore[index].inState != VOPDBG_LOCKNOTNIL)) {
        !          1012:                       PRINTIT ("%s: InState check: Null vnode ptr in entry #%d\n", funcname, index);
        !          1013:                   } else if (VopDbgStore[index].vp != NULL) {
        !          1014:                       switch (VopDbgStore[index].inState)
        !          1015:                         {
        !          1016:                           case VOPDBG_LOCKED:
        !          1017:                           case VOPDBG_LOCKNOTNIL:
        !          1018:                               if (VopDbgStore[index].inValue == 0)
        !          1019:                                 {
        !          1020:                                   PRINTIT ("%s: %d Entry: not LOCKED:", funcname, index); DBG_VOP(("\n"));
        !          1021:                                 }
        !          1022:                               break;
        !          1023:                           case VOPDBG_UNLOCKED:
        !          1024:                               if (VopDbgStore[index].inValue != 0)
        !          1025:                                 {
        !          1026:                                   PRINTIT ("%s: %d Entry: not UNLOCKED:", funcname, index); DBG_VOP(("\n"));
        !          1027:                                 }
        !          1028:                               break;
        !          1029:                         }
        !          1030:                   }
        !          1031:                   break;
        !          1032:               }
        !          1033:             default:
        !          1034:                 PRINTIT ("%s: DBG_VOP_LOCK on entry: bad lock test value: %d\n", funcname, VopDbgStore[index].errState);
        !          1035:           }
        !          1036: 
        !          1037: 
        !          1038:         if (retval != 0)
        !          1039:           {
        !          1040:             switch (VopDbgStore[index].errState)
        !          1041:               {
        !          1042:                 case VOPDBG_IGNORE:
        !          1043:                     /* Do Nothing !!! */
        !          1044:                     break;
        !          1045:                 case VOPDBG_LOCKED:
        !          1046:                 case VOPDBG_UNLOCKED:
        !          1047:                 case VOPDBG_SAME:
        !          1048:                   {
        !          1049:                       if (VopDbgStore[index].vp == NULL) {
        !          1050:                           PRINTIT ("%s: ErrState check: Null vnode ptr in entry #%d\n", funcname, index);
        !          1051:                       } else {
        !          1052:                           VopDbgStore[index].outValue = VOP_ISLOCKED(VopDbgStore[index].vp);
        !          1053:                           switch (VopDbgStore[index].errState)
        !          1054:                             {
        !          1055:                               case VOPDBG_LOCKED:
        !          1056:                                   if (VopDbgStore[index].outValue == 0)
        !          1057:                                     {
        !          1058:                                       PRINTIT ("%s: %d Error: not LOCKED:", funcname, index); DBG_VOP(("\n"));
        !          1059:                                     }
        !          1060:                                   break;
        !          1061:                               case VOPDBG_UNLOCKED:
        !          1062:                                   if (VopDbgStore[index].outValue != 0)
        !          1063:                                     {
        !          1064:                                       PRINTIT ("%s: %d Error: not UNLOCKED:", funcname, index); DBG_VOP(("\n"));
        !          1065:                                     }
        !          1066:                                   break;
        !          1067:                               case VOPDBG_SAME:
        !          1068:                                   if (VopDbgStore[index].outValue != VopDbgStore[index].inValue)
        !          1069:                                       PRINTIT ("%s: Error: In/Out locks are DIFFERENT: 0x%x, inis %d and out is %d\n", funcname, (u_int)VopDbgStore[index].vp, VopDbgStore[index].inValue, VopDbgStore[index].outValue);
        !          1070:                                   break;
        !          1071:                             }
        !          1072:                       }
        !          1073:                       break;
        !          1074:                   }
        !          1075:                 case VOPDBG_LOCKNOTNIL:
        !          1076:                     if (VopDbgStore[index].vp != NULL) {
        !          1077:                     VopDbgStore[index].outValue = VOP_ISLOCKED(VopDbgStore[index].vp);
        !          1078:                         if (VopDbgStore[index].outValue == 0)
        !          1079:                             PRINTIT ("%s: Error: %d Not LOCKED: 0x%x\n", funcname, index, (u_int)VopDbgStore[index].vp);
        !          1080:                     }
        !          1081:                     break;
        !          1082:                 default:
        !          1083:                     PRINTIT ("%s: Error: bad lock test value: %d\n", funcname, VopDbgStore[index].errState);
        !          1084:               }
        !          1085:           }
        !          1086:         else
        !          1087:           {
        !          1088:             switch (VopDbgStore[index].outState)
        !          1089:               {
        !          1090:                 case VOPDBG_IGNORE:
        !          1091:                     /* Do Nothing !!! */
        !          1092:                     break;
        !          1093:                 case VOPDBG_LOCKED:
        !          1094:                 case VOPDBG_UNLOCKED:
        !          1095:                 case VOPDBG_SAME:
        !          1096:                     if (VopDbgStore[index].vp == NULL) {
        !          1097:                         PRINTIT ("%s: OutState: Null vnode ptr in entry #%d\n", funcname, index);
        !          1098:                     };
        !          1099:                     if (VopDbgStore[index].vp != NULL)
        !          1100:                       {
        !          1101:                     VopDbgStore[index].outValue = VOP_ISLOCKED(VopDbgStore[index].vp);
        !          1102:                         switch (VopDbgStore[index].outState)
        !          1103:                           {
        !          1104:                             case VOPDBG_LOCKED:
        !          1105:                                 if (VopDbgStore[index].outValue == 0)
        !          1106:                                   {
        !          1107:                                     PRINTIT ("%s: %d Out: not LOCKED:", funcname, index); DBG_VOP(("\n"));
        !          1108:                                   }
        !          1109:                                 break;
        !          1110:                             case VOPDBG_UNLOCKED:
        !          1111:                                 if (VopDbgStore[index].outValue != 0)
        !          1112:                                   {
        !          1113:                                     PRINTIT ("%s: %d Out: not UNLOCKED:", funcname, index); DBG_VOP(("\n"));
        !          1114:                                   }
        !          1115:                                 break;
        !          1116:                             case VOPDBG_SAME:
        !          1117:                                 if (VopDbgStore[index].outValue != VopDbgStore[index].inValue)
        !          1118:                                     PRINTIT ("%s: Out: In/Out locks are DIFFERENT: 0x%x, inis %d and out is %d\n", funcname, (u_int)VopDbgStore[index].vp, VopDbgStore[index].inValue, VopDbgStore[index].outValue);
        !          1119:                                 break;
        !          1120:                           }
        !          1121:                       }
        !          1122:                     break;
        !          1123:                 case VOPDBG_LOCKNOTNIL:
        !          1124:                     if (VopDbgStore[index].vp != NULL) {
        !          1125:                     if (&((struct volfs_vndata *)(VopDbgStore[index].vp->v_data))->lock == NULL)
        !          1126:                             PRINTIT ("%s: DBG_VOP_LOCK on out: Null lock on vnode 0x%x\n", funcname, (u_int)VopDbgStore[index].vp);
        !          1127:                         else {
        !          1128:                         VopDbgStore[index].outValue = VOP_ISLOCKED(VopDbgStore[index].vp);
        !          1129:                             if (VopDbgStore[index].outValue == 0)
        !          1130:                               {
        !          1131:                                 PRINTIT ("%s: DBG_VOP_LOCK on out: Should be LOCKED:", funcname); DBG_VOP(("\n"));
        !          1132:                               }
        !          1133:                         }
        !          1134:                     }
        !          1135:                     break;
        !          1136:                 default:
        !          1137:                     PRINTIT ("%s: DBG_VOP_LOCK on out: bad lock test value: %d\n", funcname, VopDbgStore[index].outState);
        !          1138:               }
        !          1139:           }
        !          1140: 
        !          1141:         VopDbgStore[index].id = -1;            /* Invalidate the entry to allow panic-free re-use */
        !          1142:       }        
        !          1143: }
        !          1144: 
        !          1145: #endif /* DBG_VOP_TEST_LOCKS */
        !          1146: 

unix.superglobalmegacorp.com

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