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