|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.