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