|
|
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) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 23: /* ! 24: * Copyright (c) 1989, 1991, 1993, 1994 ! 25: * The Regents of the University of California. All rights reserved. ! 26: * ! 27: * Redistribution and use in source and binary forms, with or without ! 28: * modification, are permitted provided that the following conditions ! 29: * are met: ! 30: * 1. Redistributions of source code must retain the above copyright ! 31: * notice, this list of conditions and the following disclaimer. ! 32: * 2. Redistributions in binary form must reproduce the above copyright ! 33: * notice, this list of conditions and the following disclaimer in the ! 34: * documentation and/or other materials provided with the distribution. ! 35: * 3. All advertising materials mentioning features or use of this software ! 36: * must display the following acknowledgement: ! 37: * This product includes software developed by the University of ! 38: * California, Berkeley and its contributors. ! 39: * 4. Neither the name of the University nor the names of its contributors ! 40: * may be used to endorse or promote products derived from this software ! 41: * without specific prior written permission. ! 42: * ! 43: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 44: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 45: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 46: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 47: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 48: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 49: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 50: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 51: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 52: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 53: * SUCH DAMAGE. ! 54: * ! 55: * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 ! 56: */ ! 57: ! 58: #include <rev_endian_fs.h> ! 59: #include <mach_nbc.h> ! 60: #include <sys/param.h> ! 61: #include <sys/systm.h> ! 62: #include <sys/namei.h> ! 63: #include <sys/proc.h> ! 64: #include <sys/kernel.h> ! 65: #include <sys/vnode.h> ! 66: #include <sys/socket.h> ! 67: #include <sys/mount.h> ! 68: #include <sys/buf.h> ! 69: #include <sys/mbuf.h> ! 70: #include <sys/file.h> ! 71: #ifdef NeXT ! 72: #include <bsd/dev/disk.h> ! 73: #else ! 74: #include <sys/disklabel.h> ! 75: #endif ! 76: #include <sys/ioctl.h> ! 77: #include <sys/errno.h> ! 78: #include <sys/malloc.h> ! 79: ! 80: #include <miscfs/specfs/specdev.h> ! 81: ! 82: #include <ufs/ufs/quota.h> ! 83: #include <ufs/ufs/ufsmount.h> ! 84: #include <ufs/ufs/inode.h> ! 85: #include <ufs/ufs/ufs_extern.h> ! 86: ! 87: #include <ufs/ffs/fs.h> ! 88: #include <ufs/ffs/ffs_extern.h> ! 89: #if REV_ENDIAN_FS ! 90: #include <ufs/ufs/ufs_byte_order.h> ! 91: #include <architecture/byte_order.h> ! 92: #endif /* REV_ENDIAN_FS */ ! 93: ! 94: int ffs_sbupdate __P((struct ufsmount *, int)); ! 95: ! 96: struct vfsops ufs_vfsops = { ! 97: ffs_mount, ! 98: ufs_start, ! 99: ffs_unmount, ! 100: ufs_root, ! 101: ufs_quotactl, ! 102: ffs_statfs, ! 103: ffs_sync, ! 104: ffs_vget, ! 105: ffs_fhtovp, ! 106: ffs_vptofh, ! 107: ffs_init, ! 108: ffs_sysctl, ! 109: }; ! 110: ! 111: extern u_long nextgennumber; ! 112: ! 113: /* ! 114: * Called by main() when ufs is going to be mounted as root. ! 115: */ ! 116: ffs_mountroot() ! 117: { ! 118: extern struct vnode *rootvp; ! 119: struct fs *fs; ! 120: struct mount *mp; ! 121: struct proc *p = current_proc(); /* XXX */ ! 122: struct ufsmount *ump; ! 123: u_int size; ! 124: int error; ! 125: ! 126: /* ! 127: * Get vnode for rootdev. ! 128: */ ! 129: if (error = bdevvp(rootdev, &rootvp)) { ! 130: printf("ffs_mountroot: can't setup bdevvp"); ! 131: return (error); ! 132: } ! 133: if (error = vfs_rootmountalloc("ufs", "root_device", &mp)) ! 134: return (error); ! 135: if (error = ffs_mountfs(rootvp, mp, p)) { ! 136: mp->mnt_vfc->vfc_refcount--; ! 137: vfs_unbusy(mp, p); ! 138: _FREE_ZONE(mp, sizeof (struct mount), M_MOUNT); ! 139: return (error); ! 140: } ! 141: simple_lock(&mountlist_slock); ! 142: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); ! 143: simple_unlock(&mountlist_slock); ! 144: ump = VFSTOUFS(mp); ! 145: fs = ump->um_fs; ! 146: (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0); ! 147: (void)ffs_statfs(mp, &mp->mnt_stat, p); ! 148: vfs_unbusy(mp, p); ! 149: inittodr(fs->fs_time); ! 150: return (0); ! 151: } ! 152: ! 153: /* ! 154: * VFS Operations. ! 155: * ! 156: * mount system call ! 157: */ ! 158: int ! 159: ffs_mount(mp, path, data, ndp, p) ! 160: register struct mount *mp; ! 161: char *path; ! 162: caddr_t data; ! 163: struct nameidata *ndp; ! 164: struct proc *p; ! 165: { ! 166: struct vnode *devvp; ! 167: struct ufs_args args; ! 168: struct ufsmount *ump; ! 169: register struct fs *fs; ! 170: u_int size; ! 171: int error, flags; ! 172: mode_t accessmode; ! 173: ! 174: if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) ! 175: return (error); ! 176: /* ! 177: * If updating, check whether changing from read-only to ! 178: * read/write; if there is no device name, that's all we do. ! 179: */ ! 180: if (mp->mnt_flag & MNT_UPDATE) { ! 181: ump = VFSTOUFS(mp); ! 182: fs = ump->um_fs; ! 183: if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { ! 184: flags = WRITECLOSE; ! 185: if (mp->mnt_flag & MNT_FORCE) ! 186: flags |= FORCECLOSE; ! 187: if (error = ffs_flushfiles(mp, flags, p)) ! 188: return (error); ! 189: fs->fs_clean = 1; ! 190: fs->fs_ronly = 1; ! 191: if (error = ffs_sbupdate(ump, MNT_WAIT)) { ! 192: fs->fs_clean = 0; ! 193: fs->fs_ronly = 0; ! 194: return (error); ! 195: } ! 196: } ! 197: if ((mp->mnt_flag & MNT_RELOAD) && ! 198: (error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p))) ! 199: return (error); ! 200: if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) { ! 201: /* ! 202: * If upgrade to read-write by non-root, then verify ! 203: * that user has necessary permissions on the device. ! 204: */ ! 205: if (p->p_ucred->cr_uid != 0) { ! 206: devvp = ump->um_devvp; ! 207: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); ! 208: if (error = VOP_ACCESS(devvp, VREAD | VWRITE, ! 209: p->p_ucred, p)) { ! 210: VOP_UNLOCK(devvp, 0, p); ! 211: return (error); ! 212: } ! 213: VOP_UNLOCK(devvp, 0, p); ! 214: } ! 215: fs->fs_ronly = 0; ! 216: fs->fs_clean = 0; ! 217: (void) ffs_sbupdate(ump, MNT_WAIT); ! 218: } ! 219: if (args.fspec == 0) { ! 220: /* ! 221: * Process export requests. ! 222: */ ! 223: return (vfs_export(mp, &ump->um_export, &args.export)); ! 224: } ! 225: } ! 226: /* ! 227: * Not an update, or updating the name: look up the name ! 228: * and verify that it refers to a sensible block device. ! 229: */ ! 230: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); ! 231: if (error = namei(ndp)) ! 232: return (error); ! 233: devvp = ndp->ni_vp; ! 234: ! 235: if (devvp->v_type != VBLK) { ! 236: vrele(devvp); ! 237: return (ENOTBLK); ! 238: } ! 239: if (major(devvp->v_rdev) >= nblkdev) { ! 240: vrele(devvp); ! 241: return (ENXIO); ! 242: } ! 243: /* ! 244: * If mount by non-root, then verify that user has necessary ! 245: * permissions on the device. ! 246: */ ! 247: if (p->p_ucred->cr_uid != 0) { ! 248: accessmode = VREAD; ! 249: if ((mp->mnt_flag & MNT_RDONLY) == 0) ! 250: accessmode |= VWRITE; ! 251: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p); ! 252: if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) { ! 253: vput(devvp); ! 254: return (error); ! 255: } ! 256: VOP_UNLOCK(devvp, 0, p); ! 257: } ! 258: if ((mp->mnt_flag & MNT_UPDATE) == 0) ! 259: error = ffs_mountfs(devvp, mp, p); ! 260: else { ! 261: if (devvp != ump->um_devvp) ! 262: error = EINVAL; /* needs translation */ ! 263: else ! 264: vrele(devvp); ! 265: } ! 266: if (error) { ! 267: vrele(devvp); ! 268: return (error); ! 269: } ! 270: ump = VFSTOUFS(mp); ! 271: fs = ump->um_fs; ! 272: (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); ! 273: bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); ! 274: bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, ! 275: MNAMELEN); ! 276: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, ! 277: &size); ! 278: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); ! 279: (void)ffs_statfs(mp, &mp->mnt_stat, p); ! 280: return (0); ! 281: } ! 282: ! 283: /* ! 284: * Reload all incore data for a filesystem (used after running fsck on ! 285: * the root filesystem and finding things to fix). The filesystem must ! 286: * be mounted read-only. ! 287: * ! 288: * Things to do to update the mount: ! 289: * 1) invalidate all cached meta-data. ! 290: * 2) re-read superblock from disk. ! 291: * 3) re-read summary information from disk. ! 292: * 4) invalidate all inactive vnodes. ! 293: * 5) invalidate all cached file data. ! 294: * 6) re-read inode data for all active vnodes. ! 295: */ ! 296: ffs_reload(mountp, cred, p) ! 297: register struct mount *mountp; ! 298: struct ucred *cred; ! 299: struct proc *p; ! 300: { ! 301: register struct vnode *vp, *nvp, *devvp; ! 302: struct inode *ip; ! 303: struct csum *space; ! 304: struct buf *bp; ! 305: struct fs *fs, *newfs; ! 306: #ifndef NeXT ! 307: struct partinfo dpart; ! 308: #endif /* NeXT */ ! 309: int i, blks, size, error; ! 310: int32_t *lp; ! 311: #if REV_ENDIAN_FS ! 312: int rev_endian = (mountp->mnt_flag & MNT_REVEND); ! 313: #endif /* REV_ENDIAN_FS */ ! 314: ! 315: if ((mountp->mnt_flag & MNT_RDONLY) == 0) ! 316: return (EINVAL); ! 317: /* ! 318: * Step 1: invalidate all cached meta-data. ! 319: */ ! 320: devvp = VFSTOUFS(mountp)->um_devvp; ! 321: if (vinvalbuf(devvp, 0, cred, p, 0, 0)) ! 322: panic("ffs_reload: dirty1"); ! 323: /* ! 324: * Step 2: re-read superblock from disk. ! 325: */ ! 326: #ifdef NeXT ! 327: VOP_DEVBLOCKSIZE(devvp,&size); ! 328: #else ! 329: if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) ! 330: size = DEV_BSIZE; ! 331: else ! 332: size = dpart.disklab->d_secsize; ! 333: #endif ! 334: if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp)) ! 335: return (error); ! 336: newfs = (struct fs *)bp->b_data; ! 337: #if REV_ENDIAN_FS ! 338: if (rev_endian) { ! 339: byte_swap_sbin(newfs); ! 340: } ! 341: #endif /* REV_ENDIAN_FS */ ! 342: if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE || ! 343: newfs->fs_bsize < sizeof(struct fs)) { ! 344: #if REV_ENDIAN_FS ! 345: if (rev_endian) ! 346: byte_swap_sbout(newfs); ! 347: #endif /* REV_ENDIAN_FS */ ! 348: ! 349: brelse(bp); ! 350: return (EIO); /* XXX needs translation */ ! 351: } ! 352: fs = VFSTOUFS(mountp)->um_fs; ! 353: /* ! 354: * Copy pointer fields back into superblock before copying in XXX ! 355: * new superblock. These should really be in the ufsmount. XXX ! 356: * Note that important parameters (eg fs_ncg) are unchanged. ! 357: */ ! 358: bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp)); ! 359: newfs->fs_maxcluster = fs->fs_maxcluster; ! 360: bcopy(newfs, fs, (u_int)fs->fs_sbsize); ! 361: if (fs->fs_sbsize < SBSIZE) ! 362: bp->b_flags |= B_INVAL; ! 363: #if REV_ENDIAN_FS ! 364: if (rev_endian) ! 365: byte_swap_sbout(newfs); ! 366: #endif /* REV_ENDIAN_FS */ ! 367: brelse(bp); ! 368: mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; ! 369: ffs_oldfscompat(fs); ! 370: /* ! 371: * Step 3: re-read summary information from disk. ! 372: */ ! 373: blks = howmany(fs->fs_cssize, fs->fs_fsize); ! 374: space = fs->fs_csp[0]; ! 375: for (i = 0; i < blks; i += fs->fs_frag) { ! 376: size = fs->fs_bsize; ! 377: if (i + fs->fs_frag > blks) ! 378: size = (blks - i) * fs->fs_fsize; ! 379: if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, ! 380: NOCRED, &bp)) ! 381: return (error); ! 382: #if REV_ENDIAN_FS ! 383: if (rev_endian) { ! 384: /* csum swaps */ ! 385: byte_swap_ints((int *)bp->b_data, size / sizeof(int)); ! 386: } ! 387: #endif /* REV_ENDIAN_FS */ ! 388: bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size); ! 389: #if REV_ENDIAN_FS ! 390: if (rev_endian) { ! 391: /* csum swaps */ ! 392: byte_swap_ints((int *)bp->b_data, size / sizeof(int)); ! 393: } ! 394: #endif /* REV_ENDIAN_FS */ ! 395: brelse(bp); ! 396: } ! 397: /* ! 398: * We no longer know anything about clusters per cylinder group. ! 399: */ ! 400: if (fs->fs_contigsumsize > 0) { ! 401: lp = fs->fs_maxcluster; ! 402: for (i = 0; i < fs->fs_ncg; i++) ! 403: *lp++ = fs->fs_contigsumsize; ! 404: } ! 405: ! 406: loop: ! 407: simple_lock(&mntvnode_slock); ! 408: for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { ! 409: if (vp->v_mount != mountp) { ! 410: simple_unlock(&mntvnode_slock); ! 411: goto loop; ! 412: } ! 413: nvp = vp->v_mntvnodes.le_next; ! 414: /* ! 415: * Step 4: invalidate all inactive vnodes. ! 416: */ ! 417: if (vrecycle(vp, &mntvnode_slock, p)) ! 418: goto loop; ! 419: /* ! 420: * Step 5: invalidate all cached file data. ! 421: */ ! 422: simple_lock(&vp->v_interlock); ! 423: simple_unlock(&mntvnode_slock); ! 424: if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) { ! 425: goto loop; ! 426: } ! 427: if (vinvalbuf(vp, 0, cred, p, 0, 0)) ! 428: panic("ffs_reload: dirty2"); ! 429: /* ! 430: * Step 6: re-read inode data for all active vnodes. ! 431: */ ! 432: ip = VTOI(vp); ! 433: if (error = ! 434: bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), ! 435: (int)fs->fs_bsize, NOCRED, &bp)) { ! 436: vput(vp); ! 437: return (error); ! 438: } ! 439: #if REV_ENDIAN_FS ! 440: if (rev_endian) { ! 441: byte_swap_inode_in(((struct dinode *)bp->b_data + ! 442: ino_to_fsbo(fs, ip->i_number)), ip); ! 443: } else { ! 444: #endif /* REV_ENDIAN_FS */ ! 445: ip->i_din = *((struct dinode *)bp->b_data + ! 446: ino_to_fsbo(fs, ip->i_number)); ! 447: #if REV_ENDIAN_FS ! 448: } ! 449: #endif /* REV_ENDIAN_FS */ ! 450: brelse(bp); ! 451: vput(vp); ! 452: simple_lock(&mntvnode_slock); ! 453: } ! 454: simple_unlock(&mntvnode_slock); ! 455: return (0); ! 456: } ! 457: ! 458: /* ! 459: * Common code for mount and mountroot ! 460: */ ! 461: int ! 462: ffs_mountfs(devvp, mp, p) ! 463: register struct vnode *devvp; ! 464: struct mount *mp; ! 465: struct proc *p; ! 466: { ! 467: register struct ufsmount *ump; ! 468: struct buf *bp; ! 469: register struct fs *fs; ! 470: dev_t dev; ! 471: #ifdef NeXT ! 472: struct buf *cgbp; ! 473: struct cg *cgp; ! 474: int32_t clustersumoff; ! 475: #else ! 476: struct partinfo dpart; ! 477: #endif /* NeXT */ ! 478: caddr_t base, space; ! 479: int error, i, blks, size, ronly; ! 480: int32_t *lp; ! 481: struct ucred *cred; ! 482: extern struct vnode *rootvp; ! 483: u_int64_t maxfilesize; /* XXX */ ! 484: u_int dbsize = DEV_BSIZE; ! 485: #if REV_ENDIAN_FS ! 486: int rev_endian=0; ! 487: #endif /* REV_ENDIAN_FS */ ! 488: dev = devvp->v_rdev; ! 489: cred = p ? p->p_ucred : NOCRED; ! 490: /* ! 491: * Disallow multiple mounts of the same device. ! 492: * Disallow mounting of a device that is currently in use ! 493: * (except for root, which might share swap device for miniroot). ! 494: * Flush out any old buffers remaining from a previous use. ! 495: */ ! 496: if (error = vfs_mountedon(devvp)) ! 497: return (error); ! 498: if (vcount(devvp) > 1 && devvp != rootvp) ! 499: return (EBUSY); ! 500: if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0)) ! 501: return (error); ! 502: ! 503: ronly = (mp->mnt_flag & MNT_RDONLY) != 0; ! 504: if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p)) ! 505: return (error); ! 506: #ifdef NeXT ! 507: VOP_DEVBLOCKSIZE(devvp,&size); ! 508: #else ! 509: if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) ! 510: size = DEV_BSIZE; ! 511: else ! 512: size = dpart.disklab->d_secsize; ! 513: #endif ! 514: ! 515: bp = NULL; ! 516: ump = NULL; ! 517: if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, cred, &bp)) ! 518: goto out; ! 519: fs = (struct fs *)bp->b_data; ! 520: #if REV_ENDIAN_FS ! 521: if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || ! 522: fs->fs_bsize < sizeof(struct fs)) { ! 523: int magic = fs->fs_magic; ! 524: ! 525: byte_swap_ints(&magic, 1); ! 526: if (magic != FS_MAGIC) { ! 527: error = EINVAL; ! 528: goto out; ! 529: } ! 530: byte_swap_sbin(fs); ! 531: if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || ! 532: fs->fs_bsize < sizeof(struct fs)) { ! 533: byte_swap_sbout(fs); ! 534: error = EINVAL; /* XXX needs translation */ ! 535: goto out; ! 536: } ! 537: rev_endian=1; ! 538: } ! 539: #endif /* REV_ENDIAN_FS */ ! 540: if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || ! 541: fs->fs_bsize < sizeof(struct fs)) { ! 542: #if REV_ENDIAN_FS ! 543: if (rev_endian) ! 544: byte_swap_sbout(fs); ! 545: #endif /* REV_ENDIAN_FS */ ! 546: error = EINVAL; /* XXX needs translation */ ! 547: goto out; ! 548: } ! 549: ! 550: ! 551: /* Let's figure out the devblock size the file system is with */ ! 552: /* the device block size = fragment size / number of sectors per frag */ ! 553: ! 554: dbsize = fs->fs_fsize / NSPF(fs); ! 555: if(dbsize <= 0 ) { ! 556: kprintf("device blocksize computaion failed\n"); ! 557: } else { ! 558: if (VOP_IOCTL(devvp, DKIOCSETBLOCKSIZE, &dbsize, FWRITE, NOCRED, ! 559: p) != 0) { ! 560: kprintf("failed to set device blocksize\n"); ! 561: } ! 562: /* force the specfs to reread blocksize from size() */ ! 563: set_fsblocksize(devvp); ! 564: } ! 565: ! 566: ! 567: /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ ! 568: if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { ! 569: #if REV_ENDIAN_FS ! 570: if (rev_endian) ! 571: byte_swap_sbout(fs); ! 572: #endif /* REV_ENDIAN_FS */ ! 573: error = EROFS; /* needs translation */ ! 574: goto out; ! 575: } ! 576: ! 577: #ifdef NeXT ! 578: /* If we are not mounting read only, then check for overlap ! 579: * condition in cylinder group's free block map. ! 580: * If overlap exists, then force this into a read only mount ! 581: * to avoid further corruption. PR#2216969 ! 582: */ ! 583: if (ronly == 0){ ! 584: if (error = bread (devvp, fsbtodb(fs, cgtod(fs, 0)), ! 585: (int)fs->fs_cgsize, NOCRED, &cgbp)) { ! 586: brelse(cgbp); ! 587: goto out; ! 588: } ! 589: cgp = (struct cg *)cgbp->b_data; ! 590: #if REV_ENDIAN_FS ! 591: if (rev_endian) ! 592: byte_swap_cgin(cgp,fs); ! 593: #endif /* REV_ENDIAN_FS */ ! 594: if (!cg_chkmagic(cgp)){ ! 595: #if REV_ENDIAN_FS ! 596: if (rev_endian) ! 597: byte_swap_cgout(cgp,fs); ! 598: #endif /* REV_ENDIAN_FS */ ! 599: brelse(cgbp); ! 600: goto out; ! 601: } ! 602: if (cgp->cg_clustersumoff != 0) { ! 603: /* Check for overlap */ ! 604: clustersumoff = cgp->cg_freeoff + ! 605: howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY); ! 606: clustersumoff = roundup(clustersumoff, sizeof(long)); ! 607: if (cgp->cg_clustersumoff < clustersumoff) { ! 608: /* Overlap exists */ ! 609: mp->mnt_flag |= MNT_RDONLY; ! 610: ronly = 1; ! 611: } ! 612: } ! 613: #if REV_ENDIAN_FS ! 614: if (rev_endian) ! 615: byte_swap_cgout(cgp,fs); ! 616: #endif /* REV_ENDIAN_FS */ ! 617: brelse(cgbp); ! 618: } ! 619: #endif /* NeXT */ ! 620: ! 621: ump = _MALLOC(sizeof *ump, M_UFSMNT, M_WAITOK); ! 622: bzero((caddr_t)ump, sizeof *ump); ! 623: ump->um_fs = _MALLOC((u_long)fs->fs_sbsize, M_UFSMNT, ! 624: M_WAITOK); ! 625: bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize); ! 626: if (fs->fs_sbsize < SBSIZE) ! 627: bp->b_flags |= B_INVAL; ! 628: #if REV_ENDIAN_FS ! 629: if (rev_endian) ! 630: byte_swap_sbout(fs); ! 631: #endif /* REV_ENDIAN_FS */ ! 632: brelse(bp); ! 633: bp = NULL; ! 634: fs = ump->um_fs; ! 635: fs->fs_ronly = ronly; ! 636: size = fs->fs_cssize; ! 637: blks = howmany(size, fs->fs_fsize); ! 638: if (fs->fs_contigsumsize > 0) ! 639: size += fs->fs_ncg * sizeof(int32_t); ! 640: base = space = _MALLOC((u_long)size, M_UFSMNT, M_WAITOK); ! 641: base = space; ! 642: for (i = 0; i < blks; i += fs->fs_frag) { ! 643: size = fs->fs_bsize; ! 644: if (i + fs->fs_frag > blks) ! 645: size = (blks - i) * fs->fs_fsize; ! 646: if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, ! 647: cred, &bp)) { ! 648: _FREE(base, M_UFSMNT); ! 649: goto out; ! 650: } ! 651: bcopy(bp->b_data, space, (u_int)size); ! 652: #if REV_ENDIAN_FS ! 653: if (rev_endian) ! 654: byte_swap_ints((int *) space, size / sizeof(int)); ! 655: #endif /* REV_ENDIAN_FS */ ! 656: fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; ! 657: space += size; ! 658: brelse(bp); ! 659: bp = NULL; ! 660: } ! 661: if (fs->fs_contigsumsize > 0) { ! 662: fs->fs_maxcluster = lp = (int32_t *)space; ! 663: for (i = 0; i < fs->fs_ncg; i++) ! 664: *lp++ = fs->fs_contigsumsize; ! 665: } ! 666: mp->mnt_data = (qaddr_t)ump; ! 667: mp->mnt_stat.f_fsid.val[0] = (long)dev; ! 668: mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; ! 669: #ifdef NeXT ! 670: #warning hardcoded max symlen ! 671: mp->mnt_maxsymlinklen = 60; ! 672: #else ! 673: mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; ! 674: #endif ! 675: #if REV_ENDIAN_FS ! 676: if (rev_endian) ! 677: mp->mnt_flag |= MNT_REVEND; ! 678: #endif /* REV_ENDIAN_FS */ ! 679: ump->um_mountp = mp; ! 680: ump->um_dev = dev; ! 681: ump->um_devvp = devvp; ! 682: ump->um_nindir = fs->fs_nindir; ! 683: ump->um_bptrtodb = fs->fs_fsbtodb; ! 684: ump->um_seqinc = fs->fs_frag; ! 685: for (i = 0; i < MAXQUOTAS; i++) ! 686: ump->um_quotas[i] = NULLVP; ! 687: devvp->v_specflags |= SI_MOUNTEDON; ! 688: ffs_oldfscompat(fs); ! 689: ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */ ! 690: #ifdef NeXT ! 691: maxfilesize = (u_int64_t)0x100000000; /*4giga */ ! 692: #else ! 693: maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */ ! 694: #endif /* NeXT */ ! 695: if (fs->fs_maxfilesize > maxfilesize) /* XXX */ ! 696: fs->fs_maxfilesize = maxfilesize; /* XXX */ ! 697: if (ronly == 0) { ! 698: fs->fs_clean = 0; ! 699: (void) ffs_sbupdate(ump, MNT_WAIT); ! 700: } ! 701: return (0); ! 702: out: ! 703: if (bp) ! 704: brelse(bp); ! 705: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p); ! 706: if (ump) { ! 707: _FREE(ump->um_fs, M_UFSMNT); ! 708: _FREE(ump, M_UFSMNT); ! 709: mp->mnt_data = (qaddr_t)0; ! 710: } ! 711: return (error); ! 712: } ! 713: ! 714: /* ! 715: * Sanity checks for old file systems. ! 716: * ! 717: * XXX - goes away some day. ! 718: */ ! 719: ffs_oldfscompat(fs) ! 720: struct fs *fs; ! 721: { ! 722: int i; ! 723: ! 724: fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */ ! 725: fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */ ! 726: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ ! 727: fs->fs_nrpos = 8; /* XXX */ ! 728: if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ ! 729: u_int64_t sizepb = fs->fs_bsize; /* XXX */ ! 730: /* XXX */ ! 731: fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */ ! 732: for (i = 0; i < NIADDR; i++) { /* XXX */ ! 733: sizepb *= NINDIR(fs); /* XXX */ ! 734: fs->fs_maxfilesize += sizepb; /* XXX */ ! 735: } /* XXX */ ! 736: fs->fs_qbmask = ~fs->fs_bmask; /* XXX */ ! 737: fs->fs_qfmask = ~fs->fs_fmask; /* XXX */ ! 738: } /* XXX */ ! 739: return (0); ! 740: } ! 741: ! 742: /* ! 743: * unmount system call ! 744: */ ! 745: int ! 746: ffs_unmount(mp, mntflags, p) ! 747: struct mount *mp; ! 748: int mntflags; ! 749: struct proc *p; ! 750: { ! 751: register struct ufsmount *ump; ! 752: register struct fs *fs; ! 753: int error, flags; ! 754: flags = 0; ! 755: if (mntflags & MNT_FORCE) ! 756: flags |= FORCECLOSE; ! 757: if (error = ffs_flushfiles(mp, flags, p)) ! 758: return (error); ! 759: ump = VFSTOUFS(mp); ! 760: fs = ump->um_fs; ! 761: if (fs->fs_ronly == 0) { ! 762: fs->fs_clean = 1; ! 763: if (error = ffs_sbupdate(ump, MNT_WAIT)) { ! 764: fs->fs_clean = 0; ! 765: #ifndef NeXT ! 766: /* we can atleast cleanup ; as the media could be WP */ ! 767: /* & during mount, we do not check for write failures */ ! 768: /* FIXME LATER : the Correct fix would be to have */ ! 769: /* mount detect the WP media and downgrade to readonly mount */ ! 770: /* For now, here it is */ ! 771: return (error); ! 772: #endif ! 773: } ! 774: } ! 775: ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; ! 776: error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE, ! 777: NOCRED, p); ! 778: vrele(ump->um_devvp); ! 779: ! 780: _FREE(fs->fs_csp[0], M_UFSMNT); ! 781: _FREE(fs, M_UFSMNT); ! 782: _FREE(ump, M_UFSMNT); ! 783: mp->mnt_data = (qaddr_t)0; ! 784: #if REV_ENDIAN_FS ! 785: mp->mnt_flag &= ~MNT_REVEND; ! 786: #endif /* REV_ENDIAN_FS */ ! 787: return (error); ! 788: } ! 789: ! 790: /* ! 791: * Flush out all the files in a filesystem. ! 792: */ ! 793: ffs_flushfiles(mp, flags, p) ! 794: register struct mount *mp; ! 795: int flags; ! 796: struct proc *p; ! 797: { ! 798: register struct ufsmount *ump; ! 799: int i, error; ! 800: ! 801: ump = VFSTOUFS(mp); ! 802: #if QUOTA ! 803: if (mp->mnt_flag & MNT_QUOTA) { ! 804: if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) ! 805: return (error); ! 806: for (i = 0; i < MAXQUOTAS; i++) { ! 807: if (ump->um_quotas[i] == NULLVP) ! 808: continue; ! 809: quotaoff(p, mp, i); ! 810: } ! 811: /* ! 812: * Here we fall through to vflush again to ensure ! 813: * that we have gotten rid of all the system vnodes. ! 814: */ ! 815: } ! 816: #endif ! 817: error = vflush(mp, NULLVP, flags); ! 818: return (error); ! 819: } ! 820: ! 821: /* ! 822: * Get file system statistics. ! 823: */ ! 824: int ! 825: ffs_statfs(mp, sbp, p) ! 826: struct mount *mp; ! 827: register struct statfs *sbp; ! 828: struct proc *p; ! 829: { ! 830: register struct ufsmount *ump; ! 831: register struct fs *fs; ! 832: ! 833: ump = VFSTOUFS(mp); ! 834: fs = ump->um_fs; ! 835: if (fs->fs_magic != FS_MAGIC) ! 836: panic("ffs_statfs"); ! 837: sbp->f_bsize = fs->fs_fsize; ! 838: sbp->f_iosize = fs->fs_bsize; ! 839: sbp->f_blocks = fs->fs_dsize; ! 840: sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + ! 841: fs->fs_cstotal.cs_nffree; ! 842: sbp->f_bavail = freespace(fs, fs->fs_minfree); ! 843: sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; ! 844: sbp->f_ffree = fs->fs_cstotal.cs_nifree; ! 845: if (sbp != &mp->mnt_stat) { ! 846: sbp->f_type = mp->mnt_vfc->vfc_typenum; ! 847: bcopy((caddr_t)mp->mnt_stat.f_mntonname, ! 848: (caddr_t)&sbp->f_mntonname[0], MNAMELEN); ! 849: bcopy((caddr_t)mp->mnt_stat.f_mntfromname, ! 850: (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); ! 851: } ! 852: return (0); ! 853: } ! 854: ! 855: /* ! 856: * Go through the disk queues to initiate sandbagged IO; ! 857: * go through the inodes to write those that have been modified; ! 858: * initiate the writing of the super block if it has been modified. ! 859: * ! 860: * Note: we are always called with the filesystem marked `MPBUSY'. ! 861: */ ! 862: int ! 863: ffs_sync(mp, waitfor, cred, p) ! 864: struct mount *mp; ! 865: int waitfor; ! 866: struct ucred *cred; ! 867: struct proc *p; ! 868: { ! 869: struct vnode *nvp, *vp; ! 870: struct inode *ip; ! 871: struct ufsmount *ump = VFSTOUFS(mp); ! 872: struct fs *fs; ! 873: int error, allerror = 0; ! 874: ! 875: fs = ump->um_fs; ! 876: if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */ ! 877: printf("fs = %s\n", fs->fs_fsmnt); ! 878: panic("update: rofs mod"); ! 879: } ! 880: /* ! 881: * Write back each (modified) inode. ! 882: */ ! 883: simple_lock(&mntvnode_slock); ! 884: loop: ! 885: for (vp = mp->mnt_vnodelist.lh_first; ! 886: vp != NULL; ! 887: vp = nvp) { ! 888: /* ! 889: * If the vnode that we are about to sync is no longer ! 890: * associated with this mount point, start over. ! 891: */ ! 892: if (vp->v_mount != mp) ! 893: goto loop; ! 894: simple_lock(&vp->v_interlock); ! 895: nvp = vp->v_mntvnodes.le_next; ! 896: ip = VTOI(vp); ! 897: if ((vp->v_type == VNON) || (ip->i_flag & ! 898: (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && ! 899: vp->v_dirtyblkhd.lh_first == NULL) { ! 900: simple_unlock(&vp->v_interlock); ! 901: continue; ! 902: } ! 903: simple_unlock(&mntvnode_slock); ! 904: error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p); ! 905: if (error) { ! 906: simple_lock(&mntvnode_slock); ! 907: if (error == ENOENT) ! 908: goto loop; ! 909: continue; ! 910: } ! 911: if (error = VOP_FSYNC(vp, cred, waitfor, p)) ! 912: allerror = error; ! 913: VOP_UNLOCK(vp, 0, p); ! 914: vrele(vp); ! 915: simple_lock(&mntvnode_slock); ! 916: } ! 917: simple_unlock(&mntvnode_slock); ! 918: /* ! 919: * Force stale file system control information to be flushed. ! 920: */ ! 921: if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p)) ! 922: allerror = error; ! 923: #if QUOTA ! 924: qsync(mp); ! 925: #endif ! 926: /* ! 927: * Write back modified superblock. ! 928: */ ! 929: if (fs->fs_fmod != 0) { ! 930: fs->fs_fmod = 0; ! 931: fs->fs_time = time.tv_sec; ! 932: if (error = ffs_sbupdate(ump, waitfor)) ! 933: allerror = error; ! 934: } ! 935: return (allerror); ! 936: } ! 937: ! 938: /* ! 939: * Look up a FFS dinode number to find its incore vnode, otherwise read it ! 940: * in from disk. If it is in core, wait for the lock bit to clear, then ! 941: * return the inode locked. Detection and handling of mount points must be ! 942: * done by the calling routine. ! 943: */ ! 944: int ! 945: ffs_vget(mp, ino, vpp) ! 946: struct mount *mp; ! 947: ino_t ino; ! 948: struct vnode **vpp; ! 949: { ! 950: struct proc *p = current_proc(); /* XXX */ ! 951: struct fs *fs; ! 952: struct inode *ip; ! 953: struct ufsmount *ump; ! 954: struct buf *bp; ! 955: struct vnode *vp; ! 956: dev_t dev; ! 957: int i, type, error; ! 958: ! 959: ump = VFSTOUFS(mp); ! 960: dev = ump->um_dev; ! 961: if ((*vpp = ufs_ihashget(dev, ino)) != NULL) { ! 962: #if MACH_NBC ! 963: vp = *vpp; ! 964: if ((vp->v_type == VREG) && !(vp->v_vm_info)){ ! 965: vm_info_init(vp); ! 966: } ! 967: #endif /* MACH_NBC */ ! 968: return (0); ! 969: } ! 970: /* Allocate a new vnode/inode. */ ! 971: type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */ ! 972: MALLOC_ZONE(ip, struct inode *, sizeof(struct inode), type, M_WAITOK); ! 973: if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) { ! 974: FREE_ZONE(ip, sizeof(struct inode), type); ! 975: *vpp = NULL; ! 976: return (error); ! 977: } ! 978: bzero((caddr_t)ip, sizeof(struct inode)); ! 979: lockinit(&ip->i_lock, PINOD, "inode", 0, 0); ! 980: vp->v_data = ip; ! 981: ip->i_vnode = vp; ! 982: ip->i_fs = fs = ump->um_fs; ! 983: ip->i_dev = dev; ! 984: ip->i_number = ino; ! 985: #if QUOTA ! 986: for (i = 0; i < MAXQUOTAS; i++) ! 987: ip->i_dquot[i] = NODQUOT; ! 988: #endif ! 989: /* ! 990: * Put it onto its hash chain and lock it so that other requests for ! 991: * this inode will block if they arrive while we are sleeping waiting ! 992: * for old data structures to be purged or for the contents of the ! 993: * disk portion of this inode to be read. ! 994: */ ! 995: ufs_ihashins(ip); ! 996: ! 997: /* Read in the disk contents for the inode, copy into the inode. */ ! 998: if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), ! 999: (int)fs->fs_bsize, NOCRED, &bp)) { ! 1000: /* ! 1001: * The inode does not contain anything useful, so it would ! 1002: * be misleading to leave it on its hash chain. With mode ! 1003: * still zero, it will be unlinked and returned to the free ! 1004: * list by vput(). ! 1005: */ ! 1006: vput(vp); ! 1007: brelse(bp); ! 1008: *vpp = NULL; ! 1009: return (error); ! 1010: } ! 1011: #if REV_ENDIAN_FS ! 1012: if (mp->mnt_flag & MNT_REVEND) { ! 1013: byte_swap_inode_in(((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)),ip); ! 1014: } else { ! 1015: #endif /* REV_ENDIAN_FS */ ! 1016: ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)); ! 1017: #if REV_ENDIAN_FS ! 1018: } ! 1019: #endif /* REV_ENDIAN_FS */ ! 1020: brelse(bp); ! 1021: ! 1022: /* ! 1023: * Initialize the vnode from the inode, check for aliases. ! 1024: * Note that the underlying vnode may have changed. ! 1025: */ ! 1026: if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) { ! 1027: vput(vp); ! 1028: *vpp = NULL; ! 1029: return (error); ! 1030: } ! 1031: /* ! 1032: * Finish inode initialization now that aliasing has been resolved. ! 1033: */ ! 1034: ip->i_devvp = ump->um_devvp; ! 1035: VREF(ip->i_devvp); ! 1036: /* ! 1037: * Set up a generation number for this inode if it does not ! 1038: * already have one. This should only happen on old filesystems. ! 1039: */ ! 1040: if (ip->i_gen == 0) { ! 1041: if (++nextgennumber < (u_long)time.tv_sec) ! 1042: nextgennumber = time.tv_sec; ! 1043: ip->i_gen = nextgennumber; ! 1044: if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) ! 1045: ip->i_flag |= IN_MODIFIED; ! 1046: } ! 1047: /* ! 1048: * Ensure that uid and gid are correct. This is a temporary ! 1049: * fix until fsck has been changed to do the update. ! 1050: */ ! 1051: if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ ! 1052: ip->i_uid = ip->i_din.di_ouid; /* XXX */ ! 1053: ip->i_gid = ip->i_din.di_ogid; /* XXX */ ! 1054: } /* XXX */ ! 1055: ! 1056: *vpp = vp; ! 1057: #if MACH_NBC ! 1058: if ((vp->v_type == VREG) && !(vp->v_vm_info)){ ! 1059: vm_info_init(vp); ! 1060: } ! 1061: #endif /* MACH_NBC */ ! 1062: return (0); ! 1063: } ! 1064: ! 1065: /* ! 1066: * File handle to vnode ! 1067: * ! 1068: * Have to be really careful about stale file handles: ! 1069: * - check that the inode number is valid ! 1070: * - call ffs_vget() to get the locked inode ! 1071: * - check for an unallocated inode (i_mode == 0) ! 1072: * - check that the given client host has export rights and return ! 1073: * those rights via. exflagsp and credanonp ! 1074: */ ! 1075: int ! 1076: ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) ! 1077: register struct mount *mp; ! 1078: struct fid *fhp; ! 1079: struct mbuf *nam; ! 1080: struct vnode **vpp; ! 1081: int *exflagsp; ! 1082: struct ucred **credanonp; ! 1083: { ! 1084: register struct ufid *ufhp; ! 1085: struct fs *fs; ! 1086: ! 1087: ufhp = (struct ufid *)fhp; ! 1088: fs = VFSTOUFS(mp)->um_fs; ! 1089: if (ufhp->ufid_ino < ROOTINO || ! 1090: ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) ! 1091: return (ESTALE); ! 1092: return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp)); ! 1093: } ! 1094: ! 1095: /* ! 1096: * Vnode pointer to File handle ! 1097: */ ! 1098: /* ARGSUSED */ ! 1099: ffs_vptofh(vp, fhp) ! 1100: struct vnode *vp; ! 1101: struct fid *fhp; ! 1102: { ! 1103: register struct inode *ip; ! 1104: register struct ufid *ufhp; ! 1105: ! 1106: ip = VTOI(vp); ! 1107: ufhp = (struct ufid *)fhp; ! 1108: ufhp->ufid_len = sizeof(struct ufid); ! 1109: ufhp->ufid_ino = ip->i_number; ! 1110: ufhp->ufid_gen = ip->i_gen; ! 1111: return (0); ! 1112: } ! 1113: ! 1114: /* ! 1115: * Initialize the filesystem; just use ufs_init. ! 1116: */ ! 1117: int ! 1118: ffs_init(vfsp) ! 1119: struct vfsconf *vfsp; ! 1120: { ! 1121: ! 1122: return (ufs_init(vfsp)); ! 1123: } ! 1124: ! 1125: /* ! 1126: * fast filesystem related variables. ! 1127: */ ! 1128: ffs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) ! 1129: int *name; ! 1130: u_int namelen; ! 1131: void *oldp; ! 1132: size_t *oldlenp; ! 1133: void *newp; ! 1134: size_t newlen; ! 1135: struct proc *p; ! 1136: { ! 1137: extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree; ! 1138: ! 1139: /* all sysctl names at this level are terminal */ ! 1140: if (namelen != 1) ! 1141: return (ENOTDIR); /* overloaded */ ! 1142: ! 1143: switch (name[0]) { ! 1144: case FFS_CLUSTERREAD: ! 1145: return (sysctl_int(oldp, oldlenp, newp, newlen, ! 1146: &doclusterread)); ! 1147: case FFS_CLUSTERWRITE: ! 1148: return (sysctl_int(oldp, oldlenp, newp, newlen, ! 1149: &doclusterwrite)); ! 1150: case FFS_REALLOCBLKS: ! 1151: return (sysctl_int(oldp, oldlenp, newp, newlen, ! 1152: &doreallocblks)); ! 1153: case FFS_ASYNCFREE: ! 1154: return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree)); ! 1155: default: ! 1156: return (EOPNOTSUPP); ! 1157: } ! 1158: /* NOTREACHED */ ! 1159: } ! 1160: ! 1161: /* ! 1162: * Write a superblock and associated information back to disk. ! 1163: */ ! 1164: int ! 1165: ffs_sbupdate(mp, waitfor) ! 1166: struct ufsmount *mp; ! 1167: int waitfor; ! 1168: { ! 1169: register struct fs *dfs, *fs = mp->um_fs; ! 1170: register struct buf *bp; ! 1171: int blks; ! 1172: caddr_t space; ! 1173: int i, size, error, allerror = 0; ! 1174: #ifdef NeXT ! 1175: int devBlockSize=0; ! 1176: #endif /* NeXT */ ! 1177: #if REV_ENDIAN_FS ! 1178: int rev_endian=(mp->um_mountp->mnt_flag & MNT_REVEND); ! 1179: #endif /* REV_ENDIAN_FS */ ! 1180: ! 1181: /* ! 1182: * First write back the summary information. ! 1183: */ ! 1184: blks = howmany(fs->fs_cssize, fs->fs_fsize); ! 1185: space = (caddr_t)fs->fs_csp[0]; ! 1186: for (i = 0; i < blks; i += fs->fs_frag) { ! 1187: size = fs->fs_bsize; ! 1188: if (i + fs->fs_frag > blks) ! 1189: size = (blks - i) * fs->fs_fsize; ! 1190: bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), ! 1191: size, 0, 0); ! 1192: bcopy(space, bp->b_data, (u_int)size); ! 1193: #if REV_ENDIAN_FS ! 1194: if (rev_endian) { ! 1195: byte_swap_ints((int *)bp->b_data, size / sizeof(int)); ! 1196: } ! 1197: #endif /* REV_ENDIAN_FS */ ! 1198: space += size; ! 1199: if (waitfor != MNT_WAIT) ! 1200: bawrite(bp); ! 1201: else if (error = bwrite(bp)) ! 1202: allerror = error; ! 1203: } ! 1204: /* ! 1205: * Now write back the superblock itself. If any errors occurred ! 1206: * up to this point, then fail so that the superblock avoids ! 1207: * being written out as clean. ! 1208: */ ! 1209: if (allerror) ! 1210: return (allerror); ! 1211: #ifdef NeXT ! 1212: VOP_DEVBLOCKSIZE(mp->um_devvp,&devBlockSize); ! 1213: bp = getblk(mp->um_devvp, (SBOFF/devBlockSize), (int)fs->fs_sbsize, 0, 0); ! 1214: #else ! 1215: bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0); ! 1216: #endif ! 1217: bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize); ! 1218: /* Restore compatibility to old file systems. XXX */ ! 1219: dfs = (struct fs *)bp->b_data; /* XXX */ ! 1220: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ ! 1221: dfs->fs_nrpos = -1; /* XXX */ ! 1222: #if REV_ENDIAN_FS ! 1223: /* ! 1224: * Swapping bytes here ; so that in case ! 1225: * of inode format < FS_44INODEFMT appropriate ! 1226: * fields get moved ! 1227: */ ! 1228: if (rev_endian) { ! 1229: byte_swap_sbout((struct fs *)bp->b_data); ! 1230: } ! 1231: #endif /* REV_ENDIAN_FS */ ! 1232: if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */ ! 1233: int32_t *lp, tmp; /* XXX */ ! 1234: /* XXX */ ! 1235: lp = (int32_t *)&dfs->fs_qbmask; /* XXX */ ! 1236: tmp = lp[4]; /* XXX */ ! 1237: for (i = 4; i > 0; i--) /* XXX */ ! 1238: lp[i] = lp[i-1]; /* XXX */ ! 1239: lp[0] = tmp; /* XXX */ ! 1240: } /* XXX */ ! 1241: #if REV_ENDIAN_FS ! 1242: /* Note that dfs is already swapped so swap the filesize ! 1243: * before writing ! 1244: */ ! 1245: if (rev_endian) { ! 1246: dfs->fs_maxfilesize = NXSwapLongLong(mp->um_savedmaxfilesize); /* XXX */ ! 1247: } else { ! 1248: #endif /* REV_ENDIAN_FS */ ! 1249: dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */ ! 1250: #if REV_ENDIAN_FS ! 1251: } ! 1252: #endif /* REV_ENDIAN_FS */ ! 1253: if (waitfor != MNT_WAIT) ! 1254: bawrite(bp); ! 1255: else if (error = bwrite(bp)) ! 1256: allerror = error; ! 1257: ! 1258: return (allerror); ! 1259: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.