Annotation of XNU/bsd/miscfs/volfs/volfs_vnops.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     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.