|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989, 1991 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)ufs_vfsops.c 7.56 (Berkeley) 6/28/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "namei.h" ! 39: #include "proc.h" ! 40: #include "kernel.h" ! 41: #include "vnode.h" ! 42: #include "specdev.h" ! 43: #include "mount.h" ! 44: #include "buf.h" ! 45: #include "file.h" ! 46: #include "disklabel.h" ! 47: #include "ioctl.h" ! 48: #include "errno.h" ! 49: #include "malloc.h" ! 50: ! 51: #include "quota.h" ! 52: #include "fs.h" ! 53: #include "ufsmount.h" ! 54: #include "inode.h" ! 55: ! 56: struct vfsops ufs_vfsops = { ! 57: ufs_mount, ! 58: ufs_start, ! 59: ufs_unmount, ! 60: ufs_root, ! 61: ufs_quotactl, ! 62: ufs_statfs, ! 63: ufs_sync, ! 64: ufs_fhtovp, ! 65: ufs_vptofh, ! 66: ufs_init ! 67: }; ! 68: ! 69: /* ! 70: * Flag to allow forcible unmounting. ! 71: */ ! 72: int doforce = 1; ! 73: ! 74: /* ! 75: * Called by vfs_mountroot when ufs is going to be mounted as root. ! 76: * ! 77: * Name is updated by mount(8) after booting. ! 78: */ ! 79: #define ROOTNAME "root_device" ! 80: ! 81: ufs_mountroot() ! 82: { ! 83: register struct mount *mp; ! 84: extern struct vnode *rootvp; ! 85: struct proc *p = curproc; /* XXX */ ! 86: struct ufsmount *ump; ! 87: register struct fs *fs; ! 88: u_int size; ! 89: int error; ! 90: ! 91: mp = (struct mount *)malloc((u_long)sizeof(struct mount), ! 92: M_MOUNT, M_WAITOK); ! 93: mp->mnt_op = &ufs_vfsops; ! 94: mp->mnt_flag = MNT_RDONLY; ! 95: mp->mnt_exroot = 0; ! 96: mp->mnt_mounth = NULLVP; ! 97: error = mountfs(rootvp, mp, p); ! 98: if (error) { ! 99: free((caddr_t)mp, M_MOUNT); ! 100: return (error); ! 101: } ! 102: if (error = vfs_lock(mp)) { ! 103: (void)ufs_unmount(mp, 0, p); ! 104: free((caddr_t)mp, M_MOUNT); ! 105: return (error); ! 106: } ! 107: rootfs = mp; ! 108: mp->mnt_next = mp; ! 109: mp->mnt_prev = mp; ! 110: mp->mnt_vnodecovered = NULLVP; ! 111: ump = VFSTOUFS(mp); ! 112: fs = ump->um_fs; ! 113: bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt)); ! 114: fs->fs_fsmnt[0] = '/'; ! 115: bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, ! 116: MNAMELEN); ! 117: (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, ! 118: &size); ! 119: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); ! 120: (void) ufs_statfs(mp, &mp->mnt_stat, p); ! 121: vfs_unlock(mp); ! 122: inittodr(fs->fs_time); ! 123: return (0); ! 124: } ! 125: ! 126: /* ! 127: * VFS Operations. ! 128: * ! 129: * mount system call ! 130: */ ! 131: ufs_mount(mp, path, data, ndp, p) ! 132: register struct mount *mp; ! 133: char *path; ! 134: caddr_t data; ! 135: struct nameidata *ndp; ! 136: struct proc *p; ! 137: { ! 138: struct vnode *devvp; ! 139: struct ufs_args args; ! 140: struct ufsmount *ump; ! 141: register struct fs *fs; ! 142: u_int size; ! 143: int error; ! 144: ! 145: if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args))) ! 146: return (error); ! 147: /* ! 148: * Process export requests. ! 149: */ ! 150: if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) { ! 151: if (args.exflags & MNT_EXPORTED) ! 152: mp->mnt_flag |= MNT_EXPORTED; ! 153: else ! 154: mp->mnt_flag &= ~MNT_EXPORTED; ! 155: if (args.exflags & MNT_EXRDONLY) ! 156: mp->mnt_flag |= MNT_EXRDONLY; ! 157: else ! 158: mp->mnt_flag &= ~MNT_EXRDONLY; ! 159: mp->mnt_exroot = args.exroot; ! 160: } ! 161: /* ! 162: * If updating, check whether changing from read-only to ! 163: * read/write; if there is no device name, that's all we do. ! 164: */ ! 165: if (mp->mnt_flag & MNT_UPDATE) { ! 166: ump = VFSTOUFS(mp); ! 167: fs = ump->um_fs; ! 168: if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) ! 169: fs->fs_ronly = 0; ! 170: if (args.fspec == 0) ! 171: return (0); ! 172: } ! 173: /* ! 174: * Not an update, or updating the name: look up the name ! 175: * and verify that it refers to a sensible block device. ! 176: */ ! 177: ndp->ni_nameiop = LOOKUP | FOLLOW; ! 178: ndp->ni_segflg = UIO_USERSPACE; ! 179: ndp->ni_dirp = args.fspec; ! 180: if (error = namei(ndp, p)) ! 181: return (error); ! 182: devvp = ndp->ni_vp; ! 183: if (devvp->v_type != VBLK) { ! 184: vrele(devvp); ! 185: return (ENOTBLK); ! 186: } ! 187: if (major(devvp->v_rdev) >= nblkdev) { ! 188: vrele(devvp); ! 189: return (ENXIO); ! 190: } ! 191: if ((mp->mnt_flag & MNT_UPDATE) == 0) ! 192: error = mountfs(devvp, mp, p); ! 193: else { ! 194: if (devvp != ump->um_devvp) ! 195: error = EINVAL; /* needs translation */ ! 196: else ! 197: vrele(devvp); ! 198: } ! 199: if (error) { ! 200: vrele(devvp); ! 201: return (error); ! 202: } ! 203: ump = VFSTOUFS(mp); ! 204: fs = ump->um_fs; ! 205: (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size); ! 206: bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size); ! 207: bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname, ! 208: MNAMELEN); ! 209: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, ! 210: &size); ! 211: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); ! 212: (void) ufs_statfs(mp, &mp->mnt_stat, p); ! 213: return (0); ! 214: } ! 215: ! 216: /* ! 217: * Common code for mount and mountroot ! 218: */ ! 219: mountfs(devvp, mp, p) ! 220: register struct vnode *devvp; ! 221: struct mount *mp; ! 222: struct proc *p; ! 223: { ! 224: register struct ufsmount *ump = (struct ufsmount *)0; ! 225: struct buf *bp = NULL; ! 226: register struct fs *fs; ! 227: dev_t dev = devvp->v_rdev; ! 228: struct partinfo dpart; ! 229: caddr_t base, space; ! 230: int havepart = 0, blks; ! 231: int error, i, size; ! 232: int needclose = 0; ! 233: int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; ! 234: extern struct vnode *rootvp; ! 235: ! 236: /* ! 237: * Disallow multiple mounts of the same device. ! 238: * Disallow mounting of a device that is currently in use ! 239: * (except for root, which might share swap device for miniroot). ! 240: * Flush out any old buffers remaining from a previous use. ! 241: */ ! 242: if (error = mountedon(devvp)) ! 243: return (error); ! 244: if (vcount(devvp) > 1 && devvp != rootvp) ! 245: return (EBUSY); ! 246: vinvalbuf(devvp, 1); ! 247: if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p)) ! 248: return (error); ! 249: needclose = 1; ! 250: if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0) ! 251: size = DEV_BSIZE; ! 252: else { ! 253: havepart = 1; ! 254: size = dpart.disklab->d_secsize; ! 255: } ! 256: if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) ! 257: goto out; ! 258: fs = bp->b_un.b_fs; ! 259: if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || ! 260: fs->fs_bsize < sizeof(struct fs)) { ! 261: error = EINVAL; /* XXX needs translation */ ! 262: goto out; ! 263: } ! 264: ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK); ! 265: ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK, ! 266: M_WAITOK); ! 267: bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, ! 268: (u_int)fs->fs_sbsize); ! 269: if (fs->fs_sbsize < SBSIZE) ! 270: bp->b_flags |= B_INVAL; ! 271: brelse(bp); ! 272: bp = NULL; ! 273: fs = ump->um_fs; ! 274: fs->fs_ronly = ronly; ! 275: if (ronly == 0) ! 276: fs->fs_fmod = 1; ! 277: if (havepart) { ! 278: dpart.part->p_fstype = FS_BSDFFS; ! 279: dpart.part->p_fsize = fs->fs_fsize; ! 280: dpart.part->p_frag = fs->fs_frag; ! 281: dpart.part->p_cpg = fs->fs_cpg; ! 282: } ! 283: blks = howmany(fs->fs_cssize, fs->fs_fsize); ! 284: base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, ! 285: M_WAITOK); ! 286: for (i = 0; i < blks; i += fs->fs_frag) { ! 287: size = fs->fs_bsize; ! 288: if (i + fs->fs_frag > blks) ! 289: size = (blks - i) * fs->fs_fsize; ! 290: error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size, ! 291: NOCRED, &bp); ! 292: if (error) { ! 293: free((caddr_t)base, M_SUPERBLK); ! 294: goto out; ! 295: } ! 296: bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size); ! 297: fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space; ! 298: space += size; ! 299: brelse(bp); ! 300: bp = NULL; ! 301: } ! 302: mp->mnt_data = (qaddr_t)ump; ! 303: mp->mnt_stat.f_fsid.val[0] = (long)dev; ! 304: mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS; ! 305: mp->mnt_flag |= MNT_LOCAL; ! 306: ump->um_mountp = mp; ! 307: ump->um_dev = dev; ! 308: ump->um_devvp = devvp; ! 309: for (i = 0; i < MAXQUOTAS; i++) ! 310: ump->um_quotas[i] = NULLVP; ! 311: devvp->v_specflags |= SI_MOUNTEDON; ! 312: ! 313: /* Sanity checks for old file systems. XXX */ ! 314: fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ ! 315: fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ ! 316: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ ! 317: fs->fs_nrpos = 8; /* XXX */ ! 318: return (0); ! 319: out: ! 320: if (bp) ! 321: brelse(bp); ! 322: if (needclose) ! 323: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); ! 324: if (ump) { ! 325: free((caddr_t)ump->um_fs, M_SUPERBLK); ! 326: free((caddr_t)ump, M_UFSMNT); ! 327: mp->mnt_data = (qaddr_t)0; ! 328: } ! 329: return (error); ! 330: } ! 331: ! 332: /* ! 333: * Make a filesystem operational. ! 334: * Nothing to do at the moment. ! 335: */ ! 336: /* ARGSUSED */ ! 337: ufs_start(mp, flags, p) ! 338: struct mount *mp; ! 339: int flags; ! 340: struct proc *p; ! 341: { ! 342: ! 343: return (0); ! 344: } ! 345: ! 346: /* ! 347: * unmount system call ! 348: */ ! 349: ufs_unmount(mp, mntflags, p) ! 350: struct mount *mp; ! 351: int mntflags; ! 352: struct proc *p; ! 353: { ! 354: register struct ufsmount *ump; ! 355: register struct fs *fs; ! 356: int i, error, ronly, flags = 0; ! 357: ! 358: if (mntflags & MNT_FORCE) { ! 359: if (!doforce || mp == rootfs) ! 360: return (EINVAL); ! 361: flags |= FORCECLOSE; ! 362: } ! 363: mntflushbuf(mp, 0); ! 364: if (mntinvalbuf(mp)) ! 365: return (EBUSY); ! 366: ump = VFSTOUFS(mp); ! 367: #ifdef QUOTA ! 368: if (mp->mnt_flag & MNT_QUOTA) { ! 369: if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) ! 370: return (error); ! 371: for (i = 0; i < MAXQUOTAS; i++) { ! 372: if (ump->um_quotas[i] == NULLVP) ! 373: continue; ! 374: quotaoff(p, mp, i); ! 375: } ! 376: /* ! 377: * Here we fall through to vflush again to ensure ! 378: * that we have gotten rid of all the system vnodes. ! 379: */ ! 380: } ! 381: #endif ! 382: if (error = vflush(mp, NULLVP, flags)) ! 383: return (error); ! 384: fs = ump->um_fs; ! 385: ronly = !fs->fs_ronly; ! 386: ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; ! 387: error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, ! 388: NOCRED, p); ! 389: vrele(ump->um_devvp); ! 390: free((caddr_t)fs->fs_csp[0], M_SUPERBLK); ! 391: free((caddr_t)fs, M_SUPERBLK); ! 392: free((caddr_t)ump, M_UFSMNT); ! 393: mp->mnt_data = (qaddr_t)0; ! 394: mp->mnt_flag &= ~MNT_LOCAL; ! 395: return (error); ! 396: } ! 397: ! 398: /* ! 399: * Check to see if a filesystem is mounted on a block device. ! 400: */ ! 401: mountedon(vp) ! 402: register struct vnode *vp; ! 403: { ! 404: register struct vnode *vq; ! 405: ! 406: if (vp->v_specflags & SI_MOUNTEDON) ! 407: return (EBUSY); ! 408: if (vp->v_flag & VALIASED) { ! 409: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { ! 410: if (vq->v_rdev != vp->v_rdev || ! 411: vq->v_type != vp->v_type) ! 412: continue; ! 413: if (vq->v_specflags & SI_MOUNTEDON) ! 414: return (EBUSY); ! 415: } ! 416: } ! 417: return (0); ! 418: } ! 419: ! 420: /* ! 421: * Return root of a filesystem ! 422: */ ! 423: ufs_root(mp, vpp) ! 424: struct mount *mp; ! 425: struct vnode **vpp; ! 426: { ! 427: register struct inode *ip; ! 428: struct inode *nip; ! 429: struct vnode tvp; ! 430: int error; ! 431: ! 432: tvp.v_mount = mp; ! 433: ip = VTOI(&tvp); ! 434: ip->i_vnode = &tvp; ! 435: ip->i_dev = VFSTOUFS(mp)->um_dev; ! 436: error = iget(ip, (ino_t)ROOTINO, &nip); ! 437: if (error) ! 438: return (error); ! 439: *vpp = ITOV(nip); ! 440: return (0); ! 441: } ! 442: ! 443: /* ! 444: * Do operations associated with quotas ! 445: */ ! 446: ufs_quotactl(mp, cmds, uid, arg, p) ! 447: struct mount *mp; ! 448: int cmds; ! 449: uid_t uid; ! 450: caddr_t arg; ! 451: struct proc *p; ! 452: { ! 453: struct ufsmount *ump = VFSTOUFS(mp); ! 454: int cmd, type, error; ! 455: ! 456: #ifndef QUOTA ! 457: return (EOPNOTSUPP); ! 458: #else ! 459: if (uid == -1) ! 460: uid = p->p_cred->p_ruid; ! 461: cmd = cmds >> SUBCMDSHIFT; ! 462: ! 463: switch (cmd) { ! 464: case Q_GETQUOTA: ! 465: case Q_SYNC: ! 466: if (uid == p->p_cred->p_ruid) ! 467: break; ! 468: /* fall through */ ! 469: default: ! 470: if (error = suser(p->p_ucred, &p->p_acflag)) ! 471: return (error); ! 472: } ! 473: ! 474: type = cmd & SUBCMDMASK; ! 475: if ((u_int)type >= MAXQUOTAS) ! 476: return (EINVAL); ! 477: ! 478: switch (cmd) { ! 479: ! 480: case Q_QUOTAON: ! 481: return (quotaon(p, mp, type, arg)); ! 482: ! 483: case Q_QUOTAOFF: ! 484: if (vfs_busy(mp)) ! 485: return (0); ! 486: error = quotaoff(p, mp, type); ! 487: vfs_unbusy(mp); ! 488: return (error); ! 489: ! 490: case Q_SETQUOTA: ! 491: return (setquota(mp, uid, type, arg)); ! 492: ! 493: case Q_SETUSE: ! 494: return (setuse(mp, uid, type, arg)); ! 495: ! 496: case Q_GETQUOTA: ! 497: return (getquota(mp, uid, type, arg)); ! 498: ! 499: case Q_SYNC: ! 500: if (vfs_busy(mp)) ! 501: return (0); ! 502: error = qsync(mp); ! 503: vfs_unbusy(mp); ! 504: return (error); ! 505: ! 506: default: ! 507: return (EINVAL); ! 508: } ! 509: /* NOTREACHED */ ! 510: #endif ! 511: } ! 512: ! 513: /* ! 514: * Get file system statistics. ! 515: */ ! 516: ufs_statfs(mp, sbp, p) ! 517: struct mount *mp; ! 518: register struct statfs *sbp; ! 519: struct proc *p; ! 520: { ! 521: register struct ufsmount *ump; ! 522: register struct fs *fs; ! 523: ! 524: ump = VFSTOUFS(mp); ! 525: fs = ump->um_fs; ! 526: if (fs->fs_magic != FS_MAGIC) ! 527: panic("ufs_statfs"); ! 528: sbp->f_type = MOUNT_UFS; ! 529: sbp->f_fsize = fs->fs_fsize; ! 530: sbp->f_bsize = fs->fs_bsize; ! 531: sbp->f_blocks = fs->fs_dsize; ! 532: sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + ! 533: fs->fs_cstotal.cs_nffree; ! 534: sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) - ! 535: (fs->fs_dsize - sbp->f_bfree); ! 536: sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; ! 537: sbp->f_ffree = fs->fs_cstotal.cs_nifree; ! 538: if (sbp != &mp->mnt_stat) { ! 539: bcopy((caddr_t)mp->mnt_stat.f_mntonname, ! 540: (caddr_t)&sbp->f_mntonname[0], MNAMELEN); ! 541: bcopy((caddr_t)mp->mnt_stat.f_mntfromname, ! 542: (caddr_t)&sbp->f_mntfromname[0], MNAMELEN); ! 543: } ! 544: return (0); ! 545: } ! 546: ! 547: int syncprt = 0; ! 548: ! 549: /* ! 550: * Go through the disk queues to initiate sandbagged IO; ! 551: * go through the inodes to write those that have been modified; ! 552: * initiate the writing of the super block if it has been modified. ! 553: * ! 554: * Note: we are always called with the filesystem marked `MPBUSY'. ! 555: */ ! 556: ufs_sync(mp, waitfor) ! 557: struct mount *mp; ! 558: int waitfor; ! 559: { ! 560: register struct vnode *vp; ! 561: register struct inode *ip; ! 562: register struct ufsmount *ump = VFSTOUFS(mp); ! 563: register struct fs *fs; ! 564: int error, allerror = 0; ! 565: ! 566: if (syncprt) ! 567: bufstats(); ! 568: fs = ump->um_fs; ! 569: /* ! 570: * Write back modified superblock. ! 571: * Consistency check that the superblock ! 572: * is still in the buffer cache. ! 573: */ ! 574: if (fs->fs_fmod != 0) { ! 575: if (fs->fs_ronly != 0) { /* XXX */ ! 576: printf("fs = %s\n", fs->fs_fsmnt); ! 577: panic("update: rofs mod"); ! 578: } ! 579: fs->fs_fmod = 0; ! 580: fs->fs_time = time.tv_sec; ! 581: allerror = sbupdate(ump, waitfor); ! 582: } ! 583: /* ! 584: * Write back each (modified) inode. ! 585: */ ! 586: loop: ! 587: for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) { ! 588: /* ! 589: * If the vnode that we are about to sync is no longer ! 590: * associated with this mount point, start over. ! 591: */ ! 592: if (vp->v_mount != mp) ! 593: goto loop; ! 594: if (VOP_ISLOCKED(vp)) ! 595: continue; ! 596: ip = VTOI(vp); ! 597: if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 && ! 598: vp->v_dirtyblkhd == NULL) ! 599: continue; ! 600: if (vget(vp)) ! 601: goto loop; ! 602: if (vp->v_dirtyblkhd) ! 603: vflushbuf(vp, 0); ! 604: if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) && ! 605: (error = iupdat(ip, &time, &time, 0))) ! 606: allerror = error; ! 607: vput(vp); ! 608: } ! 609: /* ! 610: * Force stale file system control information to be flushed. ! 611: */ ! 612: vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0); ! 613: #ifdef QUOTA ! 614: qsync(mp); ! 615: #endif ! 616: return (allerror); ! 617: } ! 618: ! 619: /* ! 620: * Write a superblock and associated information back to disk. ! 621: */ ! 622: sbupdate(mp, waitfor) ! 623: struct ufsmount *mp; ! 624: int waitfor; ! 625: { ! 626: register struct fs *fs = mp->um_fs; ! 627: register struct buf *bp; ! 628: int blks; ! 629: caddr_t space; ! 630: int i, size, error = 0; ! 631: ! 632: bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); ! 633: bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); ! 634: /* Restore compatibility to old file systems. XXX */ ! 635: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ ! 636: bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ ! 637: if (waitfor == MNT_WAIT) ! 638: error = bwrite(bp); ! 639: else ! 640: bawrite(bp); ! 641: blks = howmany(fs->fs_cssize, fs->fs_fsize); ! 642: space = (caddr_t)fs->fs_csp[0]; ! 643: for (i = 0; i < blks; i += fs->fs_frag) { ! 644: size = fs->fs_bsize; ! 645: if (i + fs->fs_frag > blks) ! 646: size = (blks - i) * fs->fs_fsize; ! 647: bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); ! 648: bcopy(space, bp->b_un.b_addr, (u_int)size); ! 649: space += size; ! 650: if (waitfor == MNT_WAIT) ! 651: error = bwrite(bp); ! 652: else ! 653: bawrite(bp); ! 654: } ! 655: return (error); ! 656: } ! 657: ! 658: /* ! 659: * Print out statistics on the current allocation of the buffer pool. ! 660: * Can be enabled to print out on every ``sync'' by setting "syncprt" ! 661: * above. ! 662: */ ! 663: bufstats() ! 664: { ! 665: int s, i, j, count; ! 666: register struct buf *bp, *dp; ! 667: int counts[MAXBSIZE/CLBYTES+1]; ! 668: static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; ! 669: ! 670: for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) { ! 671: count = 0; ! 672: for (j = 0; j <= MAXBSIZE/CLBYTES; j++) ! 673: counts[j] = 0; ! 674: s = splbio(); ! 675: for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) { ! 676: counts[dp->b_bufsize/CLBYTES]++; ! 677: count++; ! 678: } ! 679: splx(s); ! 680: printf("%s: total-%d", bname[i], count); ! 681: for (j = 0; j <= MAXBSIZE/CLBYTES; j++) ! 682: if (counts[j] != 0) ! 683: printf(", %d-%d", j * CLBYTES, counts[j]); ! 684: printf("\n"); ! 685: } ! 686: } ! 687: ! 688: /* ! 689: * File handle to vnode ! 690: * ! 691: * Have to be really careful about stale file handles: ! 692: * - check that the inode number is in range ! 693: * - call iget() to get the locked inode ! 694: * - check for an unallocated inode (i_mode == 0) ! 695: * - check that the generation number matches ! 696: */ ! 697: ufs_fhtovp(mp, fhp, vpp) ! 698: register struct mount *mp; ! 699: struct fid *fhp; ! 700: struct vnode **vpp; ! 701: { ! 702: register struct ufid *ufhp; ! 703: register struct fs *fs; ! 704: register struct inode *ip; ! 705: struct inode *nip; ! 706: struct vnode tvp; ! 707: int error; ! 708: ! 709: ufhp = (struct ufid *)fhp; ! 710: fs = VFSTOUFS(mp)->um_fs; ! 711: if (ufhp->ufid_ino < ROOTINO || ! 712: ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) { ! 713: *vpp = NULLVP; ! 714: return (EINVAL); ! 715: } ! 716: tvp.v_mount = mp; ! 717: ip = VTOI(&tvp); ! 718: ip->i_vnode = &tvp; ! 719: ip->i_dev = VFSTOUFS(mp)->um_dev; ! 720: if (error = iget(ip, ufhp->ufid_ino, &nip)) { ! 721: *vpp = NULLVP; ! 722: return (error); ! 723: } ! 724: ip = nip; ! 725: if (ip->i_mode == 0) { ! 726: iput(ip); ! 727: *vpp = NULLVP; ! 728: return (EINVAL); ! 729: } ! 730: if (ip->i_gen != ufhp->ufid_gen) { ! 731: iput(ip); ! 732: *vpp = NULLVP; ! 733: return (EINVAL); ! 734: } ! 735: *vpp = ITOV(ip); ! 736: return (0); ! 737: } ! 738: ! 739: /* ! 740: * Vnode pointer to File handle ! 741: */ ! 742: /* ARGSUSED */ ! 743: ufs_vptofh(vp, fhp) ! 744: struct vnode *vp; ! 745: struct fid *fhp; ! 746: { ! 747: register struct inode *ip = VTOI(vp); ! 748: register struct ufid *ufhp; ! 749: ! 750: ufhp = (struct ufid *)fhp; ! 751: ufhp->ufid_len = sizeof(struct ufid); ! 752: ufhp->ufid_ino = ip->i_number; ! 753: ufhp->ufid_gen = ip->i_gen; ! 754: return (0); ! 755: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.