|
|
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: /* $NetBSD: lfs_vfsops.c,v 1.8 1995/03/09 12:06:10 mycroft Exp $ */ ! 23: ! 24: /* ! 25: * Copyright (c) 1989, 1991, 1993, 1994 ! 26: * The Regents of the University of California. All rights reserved. ! 27: * ! 28: * Redistribution and use in source and binary forms, with or without ! 29: * modification, are permitted provided that the following conditions ! 30: * are met: ! 31: * 1. Redistributions of source code must retain the above copyright ! 32: * notice, this list of conditions and the following disclaimer. ! 33: * 2. Redistributions in binary form must reproduce the above copyright ! 34: * notice, this list of conditions and the following disclaimer in the ! 35: * documentation and/or other materials provided with the distribution. ! 36: * 3. All advertising materials mentioning features or use of this software ! 37: * must display the following acknowledgement: ! 38: * This product includes software developed by the University of ! 39: * California, Berkeley and its contributors. ! 40: * 4. Neither the name of the University nor the names of its contributors ! 41: * may be used to endorse or promote products derived from this software ! 42: * without specific prior written permission. ! 43: * ! 44: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 45: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 46: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 47: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 48: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 49: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 50: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 51: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 52: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 53: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 54: * SUCH DAMAGE. ! 55: * ! 56: * @(#)lfs_vfsops.c 8.10 (Berkeley) 11/21/94 ! 57: */ ! 58: ! 59: #include <sys/param.h> ! 60: #include <sys/systm.h> ! 61: #include <sys/namei.h> ! 62: #include <sys/proc.h> ! 63: #include <sys/kernel.h> ! 64: #include <sys/vnode.h> ! 65: #include <sys/mount.h> ! 66: #include <sys/buf.h> ! 67: #include <sys/mbuf.h> ! 68: #include <sys/file.h> ! 69: #include <sys/disklabel.h> ! 70: #include <sys/ioctl.h> ! 71: #include <sys/errno.h> ! 72: #include <sys/malloc.h> ! 73: #include <sys/socket.h> ! 74: ! 75: #include <miscfs/specfs/specdev.h> ! 76: ! 77: #include <ufs/ufs/quota.h> ! 78: #include <ufs/ufs/inode.h> ! 79: #include <ufs/ufs/ufsmount.h> ! 80: #include <ufs/ufs/ufs_extern.h> ! 81: ! 82: #include <ufs/lfs/lfs.h> ! 83: #include <ufs/lfs/lfs_extern.h> ! 84: ! 85: int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *)); ! 86: ! 87: struct vfsops lfs_vfsops = { ! 88: MOUNT_LFS, ! 89: lfs_mount, ! 90: ufs_start, ! 91: lfs_unmount, ! 92: ufs_root, ! 93: ufs_quotactl, ! 94: lfs_statfs, ! 95: lfs_sync, ! 96: lfs_vget, ! 97: lfs_fhtovp, ! 98: lfs_vptofh, ! 99: lfs_init, ! 100: }; ! 101: ! 102: int ! 103: lfs_mountroot() ! 104: { ! 105: panic("lfs_mountroot"); /* XXX -- implement */ ! 106: } ! 107: ! 108: /* ! 109: * VFS Operations. ! 110: * ! 111: * mount system call ! 112: */ ! 113: lfs_mount(mp, path, data, ndp, p) ! 114: register struct mount *mp; ! 115: char *path; ! 116: caddr_t data; ! 117: struct nameidata *ndp; ! 118: struct proc *p; ! 119: { ! 120: struct vnode *devvp; ! 121: struct ufs_args args; ! 122: struct ufsmount *ump; ! 123: register struct lfs *fs; /* LFS */ ! 124: size_t size; ! 125: int error; ! 126: mode_t accessmode; ! 127: ! 128: if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) ! 129: return (error); ! 130: ! 131: /* Until LFS can do NFS right. XXX */ ! 132: if (args.export.ex_flags & MNT_EXPORTED) ! 133: return (EINVAL); ! 134: ! 135: /* ! 136: * If updating, check whether changing from read-only to ! 137: * read/write; if there is no device name, that's all we do. ! 138: */ ! 139: if (mp->mnt_flag & MNT_UPDATE) { ! 140: ump = VFSTOUFS(mp); ! 141: if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { ! 142: /* ! 143: * If upgrade to read-write by non-root, then verify ! 144: * that user has necessary permissions on the device. ! 145: */ ! 146: if (p->p_ucred->cr_uid != 0) { ! 147: VOP_LOCK(ump->um_devvp); ! 148: if (error = VOP_ACCESS(ump->um_devvp, ! 149: VREAD | VWRITE, p->p_ucred, p)) { ! 150: VOP_UNLOCK(ump->um_devvp); ! 151: return (error); ! 152: } ! 153: VOP_UNLOCK(ump->um_devvp); ! 154: } ! 155: fs->lfs_ronly = 0; ! 156: } ! 157: if (args.fspec == 0) { ! 158: /* ! 159: * Process export requests. ! 160: */ ! 161: return (vfs_export(mp, &ump->um_export, &args.export)); ! 162: } ! 163: } ! 164: /* ! 165: * Not an update, or updating the name: look up the name ! 166: * and verify that it refers to a sensible block device. ! 167: */ ! 168: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); ! 169: if (error = namei(ndp)) ! 170: return (error); ! 171: devvp = ndp->ni_vp; ! 172: if (devvp->v_type != VBLK) { ! 173: vrele(devvp); ! 174: return (ENOTBLK); ! 175: } ! 176: if (major(devvp->v_rdev) >= nblkdev) { ! 177: vrele(devvp); ! 178: return (ENXIO); ! 179: } ! 180: /* ! 181: * If mount by non-root, then verify that user has necessary ! 182: * permissions on the device. ! 183: */ ! 184: if (p->p_ucred->cr_uid != 0) { ! 185: accessmode = VREAD; ! 186: if ((mp->mnt_flag & MNT_RDONLY) == 0) ! 187: accessmode |= VWRITE; ! 188: VOP_LOCK(devvp); ! 189: if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) { ! 190: vput(devvp); ! 191: return (error); ! 192: } ! 193: VOP_UNLOCK(devvp); ! 194: } ! 195: if ((mp->mnt_flag & MNT_UPDATE) == 0) ! 196: error = lfs_mountfs(devvp, mp, p); /* LFS */ ! 197: else { ! 198: if (devvp != ump->um_devvp) ! 199: error = EINVAL; /* needs translation */ ! 200: else ! 201: vrele(devvp); ! 202: } ! 203: if (error) { ! 204: vrele(devvp); ! 205: return (error); ! 206: } ! 207: ump = VFSTOUFS(mp); ! 208: fs = ump->um_lfs; /* LFS */ ! 209: #ifdef NOTLFS /* LFS */ ! 210: (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); ! 211: bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); ! 212: bcopy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN); ! 213: #else ! 214: (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size); ! 215: bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size); ! 216: bcopy(fs->lfs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN); ! 217: #endif ! 218: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, ! 219: &size); ! 220: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); ! 221: return (0); ! 222: } ! 223: ! 224: /* ! 225: * Common code for mount and mountroot ! 226: * LFS specific ! 227: */ ! 228: int ! 229: lfs_mountfs(devvp, mp, p) ! 230: register struct vnode *devvp; ! 231: struct mount *mp; ! 232: struct proc *p; ! 233: { ! 234: extern struct vnode *rootvp; ! 235: register struct lfs *fs; ! 236: register struct ufsmount *ump; ! 237: struct vnode *vp; ! 238: struct buf *bp; ! 239: struct partinfo dpart; ! 240: dev_t dev; ! 241: int error, i, ronly, size; ! 242: struct ucred *cred; ! 243: ! 244: cred = p ? p->p_ucred : NOCRED; ! 245: /* ! 246: * Disallow multiple mounts of the same device. ! 247: * Disallow mounting of a device that is currently in use ! 248: * (except for root, which might share swap device for miniroot). ! 249: * Flush out any old buffers remaining from a previous use. ! 250: */ ! 251: if (error = vfs_mountedon(devvp)) ! 252: return (error); ! 253: if (vcount(devvp) > 1 && devvp != rootvp) ! 254: return (EBUSY); ! 255: if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) ! 256: return (error); ! 257: ! 258: ronly = (mp->mnt_flag & MNT_RDONLY) != 0; ! 259: if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) ! 260: return (error); ! 261: ! 262: if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0) ! 263: size = DEV_BSIZE; ! 264: else { ! 265: size = dpart.disklab->d_secsize; ! 266: #ifdef NEVER_USED ! 267: dpart.part->p_fstype = FS_LFS; ! 268: dpart.part->p_fsize = fs->lfs_fsize; /* frag size */ ! 269: dpart.part->p_frag = fs->lfs_frag; /* frags per block */ ! 270: dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */ ! 271: #endif ! 272: } ! 273: ! 274: /* Don't free random space on error. */ ! 275: bp = NULL; ! 276: ump = NULL; ! 277: ! 278: /* Read in the superblock. */ ! 279: if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp)) ! 280: goto out; ! 281: fs = (struct lfs *)bp->b_data; ! 282: ! 283: /* Check the basics. */ ! 284: if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE || ! 285: fs->lfs_bsize < sizeof(struct lfs)) { ! 286: error = EINVAL; /* XXX needs translation */ ! 287: goto out; ! 288: } ! 289: ! 290: /* Allocate the mount structure, copy the superblock into it. */ ! 291: // ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); ! 292: // fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK); ! 293: MALLOC(ump, struct ufsmount *, sizeof(struct ufsmount), M_UFSMNT, M_WAITOK); ! 294: MALLOC(ump->um_lfs, struct lfs *, sizeof(struct lfs), M_UFSMNT, M_WAITOK); ! 295: fs = ump->um_lfs; ! 296: bcopy(bp->b_data, fs, sizeof(struct lfs)); ! 297: if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */ ! 298: bp->b_flags |= B_INVAL; ! 299: brelse(bp); ! 300: bp = NULL; ! 301: ! 302: /* Set up the I/O information */ ! 303: fs->lfs_iocount = 0; ! 304: ! 305: /* Set up the ifile and lock aflags */ ! 306: fs->lfs_doifile = 0; ! 307: fs->lfs_writer = 0; ! 308: fs->lfs_dirops = 0; ! 309: fs->lfs_seglock = 0; ! 310: ! 311: /* Set the file system readonly/modify bits. */ ! 312: fs->lfs_ronly = ronly; ! 313: if (ronly == 0) ! 314: fs->lfs_fmod = 1; ! 315: ! 316: /* Initialize the mount structure. */ ! 317: dev = devvp->v_rdev; ! 318: mp->mnt_data = (qaddr_t)ump; ! 319: mp->mnt_stat.f_fsid.val[0] = (long)dev; ! 320: mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_LFS); ! 321: mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen; ! 322: mp->mnt_flag |= MNT_LOCAL; ! 323: ump->um_mountp = mp; ! 324: ump->um_dev = dev; ! 325: ump->um_devvp = devvp; ! 326: ump->um_bptrtodb = 0; ! 327: ump->um_seqinc = 1 << fs->lfs_fsbtodb; ! 328: ump->um_nindir = fs->lfs_nindir; ! 329: for (i = 0; i < MAXQUOTAS; i++) ! 330: ump->um_quotas[i] = NULLVP; ! 331: devvp->v_specflags |= SI_MOUNTEDON; ! 332: ! 333: /* ! 334: * We use the ifile vnode for almost every operation. Instead of ! 335: * retrieving it from the hash table each time we retrieve it here, ! 336: * artificially increment the reference count and keep a pointer ! 337: * to it in the incore copy of the superblock. ! 338: */ ! 339: if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp)) ! 340: goto out; ! 341: fs->lfs_ivnode = vp; ! 342: VREF(vp); ! 343: vput(vp); ! 344: ! 345: return (0); ! 346: out: ! 347: if (bp) ! 348: brelse(bp); ! 349: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); ! 350: if (ump) { ! 351: free(ump->um_lfs, M_UFSMNT); ! 352: free(ump, M_UFSMNT); ! 353: mp->mnt_data = (qaddr_t)0; ! 354: } ! 355: return (error); ! 356: } ! 357: ! 358: /* ! 359: * unmount system call ! 360: */ ! 361: lfs_unmount(mp, mntflags, p) ! 362: struct mount *mp; ! 363: int mntflags; ! 364: struct proc *p; ! 365: { ! 366: extern int doforce; ! 367: register struct ufsmount *ump; ! 368: register struct lfs *fs; ! 369: int i, error, flags, ronly; ! 370: ! 371: flags = 0; ! 372: if (mntflags & MNT_FORCE) ! 373: flags |= FORCECLOSE; ! 374: ! 375: ump = VFSTOUFS(mp); ! 376: fs = ump->um_lfs; ! 377: #if QUOTA ! 378: if (mp->mnt_flag & MNT_QUOTA) { ! 379: if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags)) ! 380: return (error); ! 381: for (i = 0; i < MAXQUOTAS; i++) { ! 382: if (ump->um_quotas[i] == NULLVP) ! 383: continue; ! 384: quotaoff(p, mp, i); ! 385: } ! 386: /* ! 387: * Here we fall through to vflush again to ensure ! 388: * that we have gotten rid of all the system vnodes. ! 389: */ ! 390: } ! 391: #endif ! 392: if (error = vflush(mp, fs->lfs_ivnode, flags)) ! 393: return (error); ! 394: fs->lfs_clean = 1; ! 395: if (error = VFS_SYNC(mp, 1, p->p_ucred, p)) ! 396: return (error); ! 397: if (fs->lfs_ivnode->v_dirtyblkhd.lh_first) ! 398: panic("lfs_unmount: still dirty blocks on ifile vnode\n"); ! 399: vrele(fs->lfs_ivnode); ! 400: vgone(fs->lfs_ivnode); ! 401: ! 402: ronly = !fs->lfs_ronly; ! 403: ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; ! 404: error = VOP_CLOSE(ump->um_devvp, ! 405: ronly ? FREAD : FREAD|FWRITE, NOCRED, p); ! 406: vrele(ump->um_devvp); ! 407: free(fs, M_UFSMNT); ! 408: free(ump, M_UFSMNT); ! 409: mp->mnt_data = (qaddr_t)0; ! 410: mp->mnt_flag &= ~MNT_LOCAL; ! 411: return (error); ! 412: } ! 413: ! 414: /* ! 415: * Get file system statistics. ! 416: */ ! 417: lfs_statfs(mp, sbp, p) ! 418: struct mount *mp; ! 419: register struct statfs *sbp; ! 420: struct proc *p; ! 421: { ! 422: register struct lfs *fs; ! 423: register struct ufsmount *ump; ! 424: ! 425: ump = VFSTOUFS(mp); ! 426: fs = ump->um_lfs; ! 427: if (fs->lfs_magic != LFS_MAGIC) ! 428: panic("lfs_statfs: magic"); ! 429: sbp->f_type = 0; ! 430: sbp->f_bsize = fs->lfs_bsize; ! 431: sbp->f_iosize = fs->lfs_bsize; ! 432: sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize); ! 433: sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree); ! 434: sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) - ! 435: (fs->lfs_dsize - fs->lfs_bfree); ! 436: sbp->f_bavail = dbtofsb(fs, sbp->f_bavail); ! 437: sbp->f_files = fs->lfs_nfiles; ! 438: sbp->f_ffree = sbp->f_bfree * INOPB(fs); ! 439: if (sbp != &mp->mnt_stat) { ! 440: bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); ! 441: bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); ! 442: } ! 443: strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN); ! 444: sbp->f_fstypename[MFSNAMELEN] = '\0'; ! 445: return (0); ! 446: } ! 447: ! 448: /* ! 449: * Go through the disk queues to initiate sandbagged IO; ! 450: * go through the inodes to write those that have been modified; ! 451: * initiate the writing of the super block if it has been modified. ! 452: * ! 453: * Note: we are always called with the filesystem marked `MPBUSY'. ! 454: */ ! 455: lfs_sync(mp, waitfor, cred, p) ! 456: struct mount *mp; ! 457: int waitfor; ! 458: struct ucred *cred; ! 459: struct proc *p; ! 460: { ! 461: int error; ! 462: ! 463: /* All syncs must be checkpoints until roll-forward is implemented. */ ! 464: error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0)); ! 465: #if QUOTA ! 466: qsync(mp); ! 467: #endif ! 468: return (error); ! 469: } ! 470: ! 471: /* ! 472: * Look up an LFS dinode number to find its incore vnode. If not already ! 473: * in core, read it in from the specified device. Return the inode locked. ! 474: * Detection and handling of mount points must be done by the calling routine. ! 475: */ ! 476: int ! 477: lfs_vget(mp, ino, vpp) ! 478: struct mount *mp; ! 479: ino_t ino; ! 480: struct vnode **vpp; ! 481: { ! 482: register struct lfs *fs; ! 483: register struct inode *ip; ! 484: struct buf *bp; ! 485: struct ifile *ifp; ! 486: struct vnode *vp; ! 487: struct ufsmount *ump; ! 488: daddr_t daddr; ! 489: dev_t dev; ! 490: int error; ! 491: ! 492: ump = VFSTOUFS(mp); ! 493: dev = ump->um_dev; ! 494: if ((*vpp = ufs_ihashget(dev, ino)) != NULL) ! 495: return (0); ! 496: ! 497: /* Translate the inode number to a disk address. */ ! 498: fs = ump->um_lfs; ! 499: if (ino == LFS_IFILE_INUM) ! 500: daddr = fs->lfs_idaddr; ! 501: else { ! 502: LFS_IENTRY(ifp, fs, ino, bp); ! 503: daddr = ifp->if_daddr; ! 504: brelse(bp); ! 505: if (daddr == LFS_UNUSED_DADDR) ! 506: return (ENOENT); ! 507: } ! 508: ! 509: /* Allocate new vnode/inode. */ ! 510: if (error = lfs_vcreate(mp, ino, &vp)) { ! 511: *vpp = NULL; ! 512: return (error); ! 513: } ! 514: ! 515: /* ! 516: * Put it onto its hash chain and lock it so that other requests for ! 517: * this inode will block if they arrive while we are sleeping waiting ! 518: * for old data structures to be purged or for the contents of the ! 519: * disk portion of this inode to be read. ! 520: */ ! 521: ip = VTOI(vp); ! 522: ufs_ihashins(ip); ! 523: ! 524: /* ! 525: * XXX ! 526: * This may not need to be here, logically it should go down with ! 527: * the i_devvp initialization. ! 528: * Ask Kirk. ! 529: */ ! 530: ip->i_lfs = ump->um_lfs; ! 531: ! 532: /* Read in the disk contents for the inode, copy into the inode. */ ! 533: if (error = ! 534: bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) { ! 535: /* ! 536: * The inode does not contain anything useful, so it would ! 537: * be misleading to leave it on its hash chain. With mode ! 538: * still zero, it will be unlinked and returned to the free ! 539: * list by vput(). ! 540: */ ! 541: vput(vp); ! 542: brelse(bp); ! 543: *vpp = NULL; ! 544: return (error); ! 545: } ! 546: ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data); ! 547: brelse(bp); ! 548: ! 549: /* ! 550: * Initialize the vnode from the inode, check for aliases. In all ! 551: * cases re-init ip, the underlying vnode/inode may have changed. ! 552: */ ! 553: if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) { ! 554: vput(vp); ! 555: *vpp = NULL; ! 556: return (error); ! 557: } ! 558: /* ! 559: * Finish inode initialization now that aliasing has been resolved. ! 560: */ ! 561: ip->i_devvp = ump->um_devvp; ! 562: VREF(ip->i_devvp); ! 563: *vpp = vp; ! 564: return (0); ! 565: } ! 566: ! 567: /* ! 568: * File handle to vnode ! 569: * ! 570: * Have to be really careful about stale file handles: ! 571: * - check that the inode number is valid ! 572: * - call lfs_vget() to get the locked inode ! 573: * - check for an unallocated inode (i_mode == 0) ! 574: * - check that the given client host has export rights and return ! 575: * those rights via. exflagsp and credanonp ! 576: * ! 577: * XXX ! 578: * use ifile to see if inode is allocated instead of reading off disk ! 579: * what is the relationship between my generational number and the NFS ! 580: * generational number. ! 581: */ ! 582: int ! 583: lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) ! 584: register struct mount *mp; ! 585: struct fid *fhp; ! 586: struct mbuf *nam; ! 587: struct vnode **vpp; ! 588: int *exflagsp; ! 589: struct ucred **credanonp; ! 590: { ! 591: register struct ufid *ufhp; ! 592: ! 593: ufhp = (struct ufid *)fhp; ! 594: if (ufhp->ufid_ino < ROOTINO) ! 595: return (ESTALE); ! 596: return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); ! 597: } ! 598: ! 599: /* ! 600: * Vnode pointer to File handle ! 601: */ ! 602: /* ARGSUSED */ ! 603: lfs_vptofh(vp, fhp) ! 604: struct vnode *vp; ! 605: struct fid *fhp; ! 606: { ! 607: register struct inode *ip; ! 608: register struct ufid *ufhp; ! 609: ! 610: ip = VTOI(vp); ! 611: ufhp = (struct ufid *)fhp; ! 612: ufhp->ufid_len = sizeof(struct ufid); ! 613: ufhp->ufid_ino = ip->i_number; ! 614: ufhp->ufid_gen = ip->i_gen; ! 615: return (0); ! 616: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.