home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / ufs / ufs_vfsops.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-28  |  17.9 KB  |  756 lines

  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. }
  756.