+ register struct inode *ip;
+ struct inode *nip;
+ struct vnode tvp;
+ int error;
+
+ tvp.v_mount = mp;
+ ip = VTOI(&tvp);
+ ip->i_vnode = &tvp;
+ ip->i_dev = VFSTOUFS(mp)->um_dev;
+ error = iget(ip, (ino_t)ROOTINO, &nip);
+ if (error)
+ return (error);
+ *vpp = ITOV(nip);
+ return (0);
+}
+
+/*
+ * Do operations associated with quotas
+ */
+ufs_quotactl(mp, cmds, uid, arg)
+ struct mount *mp;
+ int cmds;
+ uid_t uid;
+ caddr_t arg;
+{
+ register struct nameidata *ndp = &u.u_nd;
+ struct ufsmount *ump = VFSTOUFS(mp);
+ struct proc *p = u.u_procp; /* XXX */
+ int cmd, type, error;
+
+#ifndef QUOTA
+ return (EOPNOTSUPP);
+#else
+ if (uid == -1)
+ uid = p->p_ruid;
+ cmd = cmds >> SUBCMDSHIFT;
+
+ switch (cmd) {
+ case Q_GETQUOTA:
+ case Q_SYNC:
+ if (uid == p->p_ruid)
+ break;
+ /* fall through */
+ default:
+ if (error = suser(ndp->ni_cred, &u.u_acflag))
+ return (error);
+ }
+
+ type = cmd & SUBCMDMASK;
+ if ((u_int)type >= MAXQUOTAS)
+ return (EINVAL);
+
+ switch (cmd) {
+
+ case Q_QUOTAON:
+ return (quotaon(ndp, mp, type, arg));
+
+ case Q_QUOTAOFF:
+ if (vfs_busy(mp))
+ return (0);
+ error = quotaoff(mp, type);
+ vfs_unbusy(mp);
+ return (error);
+
+ case Q_SETQUOTA:
+ return (setquota(mp, uid, type, arg));
+
+ case Q_SETUSE:
+ return (setuse(mp, uid, type, arg));
+
+ case Q_GETQUOTA:
+ return (getquota(mp, uid, type, arg));
+
+ case Q_SYNC:
+ if (vfs_busy(mp))
+ return (0);
+ error = qsync(mp);
+ vfs_unbusy(mp);
+ return (error);
+
+ default:
+ return (EINVAL);
+ }
+ /* NOTREACHED */
+#endif
+}
+
+/*
+ * Get file system statistics.
+ */
+ufs_statfs(mp, sbp)
+ struct mount *mp;
+ register struct statfs *sbp;
+{
+ register struct ufsmount *ump;
+ register struct fs *fs;
+
+ ump = VFSTOUFS(mp);
+ fs = ump->um_fs;
+ if (fs->fs_magic != FS_MAGIC)
+ panic("ufs_statfs");
+ sbp->f_type = MOUNT_UFS;
+ sbp->f_fsize = fs->fs_fsize;
+ sbp->f_bsize = fs->fs_bsize;
+ sbp->f_blocks = fs->fs_dsize;
+ sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
+ fs->fs_cstotal.cs_nffree;
+ sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
+ (fs->fs_dsize - sbp->f_bfree);
+ sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
+ sbp->f_ffree = fs->fs_cstotal.cs_nifree;
+ if (sbp != &mp->mnt_stat) {
+ bcopy((caddr_t)mp->mnt_stat.f_mntonname,
+ (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
+ bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
+ (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
+ }
+ return (0);
+}
+
+int syncprt = 0;
+
+/*
+ * Go through the disk queues to initiate sandbagged IO;
+ * go through the inodes to write those that have been modified;
+ * initiate the writing of the super block if it has been modified.
+ *
+ * Note: we are always called with the filesystem marked `MPBUSY'.
+ */
+ufs_sync(mp, waitfor)
+ struct mount *mp;
+ int waitfor;
+{
+ register struct vnode *vp;
+ register struct inode *ip;
+ register struct ufsmount *ump = VFSTOUFS(mp);
+ register struct fs *fs;
+ int error, allerror = 0;
+
+ if (syncprt)
+ bufstats();
+ fs = ump->um_fs;
+ /*
+ * Write back modified superblock.
+ * Consistency check that the superblock
+ * is still in the buffer cache.
+ */
+ if (fs->fs_fmod != 0) {
+ if (fs->fs_ronly != 0) { /* XXX */
+ printf("fs = %s\n", fs->fs_fsmnt);
+ panic("update: rofs mod");
+ }
+ fs->fs_fmod = 0;
+ fs->fs_time = time.tv_sec;
+ allerror = sbupdate(ump, waitfor);
+ }
+ /*
+ * Write back each (modified) inode.
+ */
+loop:
+ for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
+ /*
+ * If the vnode that we are about to sync is no longer
+ * associated with this mount point, start over.
+ */
+ if (vp->v_mount != mp)
+ goto loop;
+ ip = VTOI(vp);
+ if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 &&
+ vp->v_dirtyblkhd == NULL)
+ continue;
+ if (vget(vp))
+ goto loop;
+ if (vp->v_dirtyblkhd)
+ vflushbuf(vp, 0);
+ if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) &&
+ (error = iupdat(ip, &time, &time, 0)))
+ allerror = error;
+ vput(vp);
+ }
+ /*
+ * Force stale file system control information to be flushed.
+ */
+ vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
+#ifdef QUOTA
+ qsync(mp);
+#endif
+ return (allerror);
+}
+
+/*
+ * Write a superblock and associated information back to disk.
+ */
+sbupdate(mp, waitfor)
+ struct ufsmount *mp;
+ int waitfor;
+{
+ register struct fs *fs = mp->um_fs;