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