Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!constellation!osuunx.ucc.okstate.edu!moe.ksu.ksu.edu!vixen.cso.uiuc.edu!uwm.edu!cs.utexas.edu!uunet!haven.umd.edu!umd5.umd.edu!elea.umd.edu!mark From: mark@elea.umd.edu (Mark Sienkiewicz) Newsgroups: comp.os.386bsd.misc Subject: Here are fs_clean patches Date: 4 Oct 1993 14:29:30 GMT Organization: Zeno, IPST, University of Maryland Lines: 889 Message-ID: <28pc0a$pcf@umd5.umd.edu> NNTP-Posting-Host: elea.umd.edu I got enough mail about my fs_clean patches, so here they are. Enjoy. Mark S. --- This is my fs_clean hack. If you're getting this in the mail, it's because I got mail from you. If you're seeing this in news, it's because so many other people asked me for it. :) This was written in June 1993, during a several week period when Netbsd-current didn't work on my machine. Therefore the diffs are relative to Netbsd 0.8, which I was running at the time. The notes are written from the same perspective. If you aren't running Netbsd 0.8, you can probably still apply the diffs by hand. As usual, pay attention to what you are doing, I provide no warranty, etc. The only thing I claim for this code is "It works for me". The file "clean" is a description of the changes. Also read the block comment in kern_xxx.c -- it's important. Enjoy. Mark S. # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # clean # clean_fsck.diff # clean_kern.diff # echo x - clean sed 's/^X//' >clean << 'END-of-clean' XThis is a set of patches to implement the clean-bit in the UFS super block. X X* When you mount a disk for read/write, it clears the fs_clean field of X the super block and writes it back to the disk immediately. X X* When you unmount the disk, it sets fs_clean in the super block and writes X it back. X X* When you halt/reboot, it forcibly unmounts all mounted filesystems. X X* fsck -p skips nearly all the checks if fs_clean is set in the super block. X X* Disks are **not** required to be clean when you mount them. This is X because I think restricting mounts that way is the "Wrong Thing To Do". X fsck does not set the clean bit when it cleans a disk, since nobody X cares. X X XNotes: X XThese patches are relative to NetBSD 0.8. I _tried_ to do them to XNetbsd-current, but I have not been able to get a -current kernel to Xwork for over a month. I've been using these changes since mid-June, Xbut kept hoping to get a -current to base the diffs on. Since I can't, Xhere's the patches... X XThere are two sets of diffs- clean_kern.diff applies to the 0.8 kernel. Xclean_fsck.diff applies to fsck. X Xdoforce in ufs_vops.c must be true or the it doesn't work when the reboot Xsystem call unmounts the filesystems. It still safely syncs the disks, but Xit won't write back the clean bit. X XThe patched reboot() system call talks when it is unmounting the filesystems. XIt can't identify the FS (except root), but you at least get some clue Xwhat's going on. X XEach filesystem type checks to see if it is unmounting rootfs. This Xis bogus. It should be done in unmount, not duplicated in every file Xsystem driver. I *need* to be able to unmount rootfs, so I fixed this Xto check for rootfs in the unmount system call. This caused me to change XUFS, NFS and ISOFS. X XThe system dependent code has a loop in boot() that goes through the Xdisk buffers and flushes them. Since I've already done a sync() on each Xfilesystem [whether it could be unmounted or not], this is redundant. The Xsystem dependent code is also the wrong place for it. In my diffs I left Xit as '#if 0', but it could as well have been deleted. X XDELAY() doesn't seem to work as advertised on my system. Comments in Xthe code say DELAY(1) delays 1 microsecond, but seems more like about 10 Xon my system. See comments in machdep.c for how this might affect you. X XI found a bug in ufs - in the unmount stuff is says X ronly = ! ...->fs_ronly; Xthe ! is incorrect. X Xin ufs, sbupdate() didn't return errors correctly. If the super block Xspanned several disk blocks, it didn't notice an error writing earlier Xblocks if the last block did not have an error. X END-of-clean echo x - clean_fsck.diff sed 's/^X//' >clean_fsck.diff << 'END-of-clean_fsck.diff' X*** main.c.org Sat Jul 3 10:17:36 1993 X--- main.c Sat Jul 3 10:35:00 1993 X*************** X*** 182,201 **** X--- 182,207 ---- X } X /* X * 1: scan inodes tallying blocks used X */ X if (preen == 0) { X printf("** Last Mounted on %s\n", sblock.fs_fsmnt); X if (hotroot) X printf("** Root file system\n"); X printf("** Phase 1 - Check Blocks and Sizes\n"); X } X+ else { X+ if (sblock.fs_clean) { X+ printf(" - unmounted cleanly\n"); X+ return(0); X+ } X+ } X pass1(); X X /* X * 1b: locate first references to duplicates, if any X */ X if (duplist) { X if (preen) X pfatal("INTERNAL ERROR: dups with -p"); X printf("** Phase 1b - Rescan For More DUPS\n"); X pass1b(); X*** setup.c.org Sat Jul 3 10:17:42 1993 X--- setup.c Sat Jul 3 10:35:30 1993 X*************** X*** 86,107 **** X } X if ((statb.st_mode & S_IFMT) != S_IFCHR) { X pfatal("%s is not a character device", dev); X if (reply("CONTINUE") == 0) X return (0); X } X if ((fsreadfd = open(dev, O_RDONLY)) < 0) { X printf("Can't open %s: %s\n", dev, strerror(errno)); X return (0); X } X! if (preen == 0) X! printf("** %s", dev); X if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { X fswritefd = -1; X if (preen) X pfatal("NO WRITE ACCESS"); X printf(" (NO WRITE)"); X } X if (preen == 0) X printf("\n"); X fsmodified = 0; X lfdir = 0; X--- 86,106 ---- X } X if ((statb.st_mode & S_IFMT) != S_IFCHR) { X pfatal("%s is not a character device", dev); X if (reply("CONTINUE") == 0) X return (0); X } X if ((fsreadfd = open(dev, O_RDONLY)) < 0) { X printf("Can't open %s: %s\n", dev, strerror(errno)); X return (0); X } X! printf("** %s", dev); X if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) { X fswritefd = -1; X if (preen) X pfatal("NO WRITE ACCESS"); X printf(" (NO WRITE)"); X } X if (preen == 0) X printf("\n"); X fsmodified = 0; X lfdir = 0; X*************** X*** 141,161 **** X "SEARCH FOR ALTERNATE SUPER-BLOCK", X "FAILED. YOU MUST USE THE", X "-b OPTION TO FSCK TO SPECIFY THE", X "LOCATION OF AN ALTERNATE", X "SUPER-BLOCK TO SUPPLY NEEDED", X "INFORMATION; SEE fsck(8)."); X return(0); X } X pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); X } X- printf("clean flag is %d\n",sblock.fs_clean); X maxfsblock = sblock.fs_size; X maxino = sblock.fs_ncg * sblock.fs_ipg; X /* X * Check and potentially fix certain fields in the super block. X */ X if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) { X pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); X if (reply("SET TO DEFAULT") == 1) { X sblock.fs_optim = FS_OPTTIME; X sbdirty(); X--- 140,159 ---- END-of-clean_fsck.diff echo x - clean_kern.diff sed 's/^X//' >clean_kern.diff << 'END-of-clean_kern.diff' X*** ./kern/vfs_syscalls.c.orig Sun Mar 21 05:46:23 1993 X--- ./kern/vfs_syscalls.c Sat Jul 3 12:32:21 1993 X*************** X*** 233,252 **** X--- 233,256 ---- X vp = ndp->ni_vp; X /* X * Must be the root of the filesystem X */ X if ((vp->v_flag & VROOT) == 0) { X vput(vp); X return (EINVAL); X } X mp = vp->v_mount; X vput(vp); X+ if (mp == rootfs) { X+ return(EINVAL); /* invalid to unmount root */ X+ } X+ X return (dounmount(mp, uap->flags, p)); X } X X /* X * Do an unmount. X */ X dounmount(mp, flags, p) X register struct mount *mp; X int flags; X struct proc *p; X*************** X*** 257,285 **** X coveredvp = mp->mnt_vnodecovered; X if (vfs_busy(mp)) X return (EBUSY); X mp->mnt_flag |= MNT_UNMOUNT; X if (error = vfs_lock(mp)) X return (error); X X vnode_pager_umount(mp); /* release cached vnodes */ X cache_purgevfs(mp); /* remove cache entries for this file sys */ X if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE)) X error = VFS_UNMOUNT(mp, flags, p); X mp->mnt_flag &= ~MNT_UNMOUNT; X vfs_unbusy(mp); X if (error) { X vfs_unlock(mp); X } else { X! vrele(coveredvp); X! vfs_remove(mp); X! free((caddr_t)mp, M_MOUNT); X } X return (error); X } X X /* X * Sync system call. X * Sync each mounted filesystem. X */ X /* ARGSUSED */ X sync(p, uap, retval) X--- 261,298 ---- X coveredvp = mp->mnt_vnodecovered; X if (vfs_busy(mp)) X return (EBUSY); X mp->mnt_flag |= MNT_UNMOUNT; X if (error = vfs_lock(mp)) X return (error); X X vnode_pager_umount(mp); /* release cached vnodes */ X cache_purgevfs(mp); /* remove cache entries for this file sys */ X if ((error = VFS_SYNC(mp, MNT_WAIT)) == 0 || (flags & MNT_FORCE)) X+ { X error = VFS_UNMOUNT(mp, flags, p); X+ } X mp->mnt_flag &= ~MNT_UNMOUNT; X vfs_unbusy(mp); X if (error) { X vfs_unlock(mp); X } else { X! if (coveredvp) X! vrele(coveredvp); X! if (! (flags & MNT_REBOOTING)) { X! /* X! * don't remove from the list if rebooting because X! * you will hose the loop in reboot() X! */ X! vfs_remove(mp); X! free((caddr_t)mp, M_MOUNT); X! } X } X return (error); X } X X /* X * Sync system call. X * Sync each mounted filesystem. X */ X /* ARGSUSED */ X sync(p, uap, retval) X*** ./kern/kern_xxx.c.orig Fri Apr 2 08:24:59 1993 X--- ./kern/kern_xxx.c Sat Jul 3 10:47:20 1993 X*************** X*** 31,50 **** X--- 31,51 ---- X * SUCH DAMAGE. X * X * @(#)kern_xxx.c 7.17 (Berkeley) 4/20/91 X */ X X #include "param.h" X #include "systm.h" X #include "kernel.h" X #include "proc.h" X #include "reboot.h" X+ #include "mount.h" X X /* ARGSUSED */ X gethostid(p, uap, retval) X struct proc *p; X void *uap; X long *retval; X { X X *retval = hostid; X return (0); X*************** X*** 139,161 **** X--- 140,192 ---- X X /* ARGSUSED */ X reboot(p, uap, retval) X struct proc *p; X struct args { X int opt; X } *uap; X int *retval; X { X int error; X+ struct mount *m; X+ int x; X X if (error = suser(p->p_ucred, &p->p_acflag)) X return (error); X+ X+ /* X+ * unmount all filesystems. We don't necessarily know that X+ * it will work, so we can't just run until rootfs->mnt_next == rootfs. X+ * As is, we run down the list and unmount each, but we ask dounmount() X+ * not to remove the unmounted vnode from the list because we don't X+ * want it to hose the list we are traversing. Since we will X+ * halt shortly, it doesn't matter that we don't free things. X+ * dounmount() returns an error code, but there isn't enough X+ * left to know which filesystem it was. Also, you can't abort X+ * the reboot because the list of mounted filesystems may be in X+ * an invalid state. The "unmounting" messages may give you a clue X+ * which filesystem had the problem, but you should probably fsck X+ * everything if you get an error. X+ */ X+ for (m = rootfs->mnt_next ; m != rootfs; m=m->mnt_next) X+ { X+ printf("unmounting\n"); X+ if (dounmount(m,MNT_FORCE | MNT_REBOOTING,p)) X+ printf("trouble unmounting a non-root fs- err %d\n", X+ x); X+ } X+ /* X+ * make sure to unmount root last. Does this really matter? X+ */ X+ printf("unmounting root\n"); X+ if (dounmount(rootfs,MNT_FORCE | MNT_REBOOTING,p)) X+ printf("trouble unmounting root - err %d\n",x); X boot(uap->opt); X return (0); X } X X #ifdef COMPAT_43 X oquota() X { X X return (ENOSYS); X } X*** ./nfs/nfs_vfsops.c.orig Sat Jul 3 12:27:54 1993 X--- ./nfs/nfs_vfsops.c Sat Jul 3 12:28:32 1993 X*************** X*** 449,469 **** X int mntflags; X struct proc *p; X { X register struct nfsmount *nmp; X struct nfsnode *np; X struct vnode *vp; X int error, flags = 0; X extern int doforce; X X if (mntflags & MNT_FORCE) { X! if (!doforce || mp == rootfs) X return (EINVAL); X flags |= FORCECLOSE; X } X nmp = VFSTONFS(mp); X /* X * Clear out the buffer cache X */ X mntflushbuf(mp, 0); X if (mntinvalbuf(mp)) X return (EBUSY); X--- 449,469 ---- X int mntflags; X struct proc *p; X { X register struct nfsmount *nmp; X struct nfsnode *np; X struct vnode *vp; X int error, flags = 0; X extern int doforce; X X if (mntflags & MNT_FORCE) { X! if (!doforce) X return (EINVAL); X flags |= FORCECLOSE; X } X nmp = VFSTONFS(mp); X /* X * Clear out the buffer cache X */ X mntflushbuf(mp, 0); X if (mntinvalbuf(mp)) X return (EBUSY); X*** ./sys/mount.h.orig Sat Apr 10 16:19:45 1993 X--- ./sys/mount.h Sat Jul 3 09:55:26 1993 X*************** X*** 180,201 **** X #define VFS_FHTOVP(MP, FIDP, VPP) (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP) X #define VFS_VPTOFH(VP, FIDP) (*(VP)->v_mount->mnt_op->vfs_vptofh)(VP, FIDP) X #endif /* KERNEL */ X X /* X * Flags for various system call interfaces. X * X * forcibly flags for vfs_umount(). X * waitfor flags to vfs_sync() and getfsstat() X */ X! #define MNT_FORCE 1 X! #define MNT_NOFORCE 2 X #define MNT_WAIT 1 X #define MNT_NOWAIT 2 X X /* X * Generic file handle X */ X struct fhandle { X fsid_t fh_fsid; /* File system id of mount point */ X struct fid fh_fid; /* Id of file */ X }; X--- 180,203 ---- X #define VFS_FHTOVP(MP, FIDP, VPP) (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, VPP) X #define VFS_VPTOFH(VP, FIDP) (*(VP)->v_mount->mnt_op->vfs_vptofh)(VP, FIDP) X #endif /* KERNEL */ X X /* X * Flags for various system call interfaces. X * X * forcibly flags for vfs_umount(). X * waitfor flags to vfs_sync() and getfsstat() X */ X! #define MNT_FORCE 1 /* force unmount */ X! #define MNT_NOFORCE 2 /* don't force unmount */ X! #define MNT_REBOOTING 4 /* unmounting as part of reboot */ X! X #define MNT_WAIT 1 X #define MNT_NOWAIT 2 X X /* X * Generic file handle X */ X struct fhandle { X fsid_t fh_fsid; /* File system id of mount point */ X struct fid fh_fid; /* Id of file */ X }; X*** ./ufs/ufs_vfsops.c.orig Sun Mar 21 05:46:04 1993 X--- ./ufs/ufs_vfsops.c Sat Jul 3 09:55:25 1993 X*************** X*** 161,180 **** X--- 161,184 ---- X } X /* X * If updating, check whether changing from read-only to X * read/write; if there is no device name, that's all we do. X */ X if (mp->mnt_flag & MNT_UPDATE) { X ump = VFSTOUFS(mp); X fs = ump->um_fs; X if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) X fs->fs_ronly = 0; X+ if (fs->fs_ronly == 0) { X+ fs->fs_clean=0; X+ sbupdate(ump,MNT_WAIT); X+ } X if (args.fspec == 0) X return (0); X } X /* X * Not an update, or updating the name: look up the name X * and verify that it refers to a sensible block device. X */ X ndp->ni_nameiop = LOOKUP | FOLLOW; X ndp->ni_segflg = UIO_USERSPACE; X ndp->ni_dirp = args.fspec; X*************** X*** 267,287 **** X--- 271,294 ---- X M_WAITOK); X bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs, X (u_int)fs->fs_sbsize); X if (fs->fs_sbsize < SBSIZE) X bp->b_flags |= B_INVAL; X brelse(bp); X bp = NULL; X fs = ump->um_fs; X fs->fs_ronly = ronly; X if (ronly == 0) X+ { X fs->fs_fmod = 1; X+ fs->fs_clean = 0; /* don't sbupdate() yet! */ X+ } X if (havepart) { X dpart.part->p_fstype = FS_BSDFFS; X dpart.part->p_fsize = fs->fs_fsize; X dpart.part->p_frag = fs->fs_frag; X dpart.part->p_cpg = fs->fs_cpg; X } X blks = howmany(fs->fs_cssize, fs->fs_fsize); X base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK, X M_WAITOK); X for (i = 0; i < blks; i += fs->fs_frag) { X*************** X*** 309,328 **** X--- 316,337 ---- X ump->um_devvp = devvp; X for (i = 0; i < MAXQUOTAS; i++) X ump->um_quotas[i] = NULLVP; X devvp->v_specflags |= SI_MOUNTEDON; X X /* Sanity checks for old file systems. XXX */ X fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */ X fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */ X if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ X fs->fs_nrpos = 8; /* XXX */ X+ if (ronly == 0) X+ sbupdate(ump,MNT_WAIT); X return (0); X out: X if (bp) X brelse(bp); X if (needclose) X (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p); X if (ump) { X free((caddr_t)ump->um_fs, M_SUPERBLK); X free((caddr_t)ump, M_UFSMNT); X mp->mnt_data = (qaddr_t)0; X*************** X*** 350,370 **** X ufs_unmount(mp, mntflags, p) X struct mount *mp; X int mntflags; X struct proc *p; X { X register struct ufsmount *ump; X register struct fs *fs; X int i, error, ronly, flags = 0; X X if (mntflags & MNT_FORCE) { X! if (!doforce || mp == rootfs) X return (EINVAL); X flags |= FORCECLOSE; X } X mntflushbuf(mp, 0); X if (mntinvalbuf(mp)) X return (EBUSY); X ump = VFSTOUFS(mp); X #ifdef QUOTA X if (mp->mnt_flag & MNT_QUOTA) { X if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) X--- 359,379 ---- X ufs_unmount(mp, mntflags, p) X struct mount *mp; X int mntflags; X struct proc *p; X { X register struct ufsmount *ump; X register struct fs *fs; X int i, error, ronly, flags = 0; X X if (mntflags & MNT_FORCE) { X! if (!doforce) X return (EINVAL); X flags |= FORCECLOSE; X } X mntflushbuf(mp, 0); X if (mntinvalbuf(mp)) X return (EBUSY); X ump = VFSTOUFS(mp); X #ifdef QUOTA X if (mp->mnt_flag & MNT_QUOTA) { X if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) X*************** X*** 376,396 **** X } X /* X * Here we fall through to vflush again to ensure X * that we have gotten rid of all the system vnodes. X */ X } X #endif X if (error = vflush(mp, NULLVP, flags)) X return (error); X fs = ump->um_fs; X! ronly = !fs->fs_ronly; X ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; X error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, X NOCRED, p); X vrele(ump->um_devvp); X free((caddr_t)fs->fs_csp[0], M_SUPERBLK); X free((caddr_t)fs, M_SUPERBLK); X free((caddr_t)ump, M_UFSMNT); X mp->mnt_data = (qaddr_t)0; X mp->mnt_flag &= ~MNT_LOCAL; X return (error); X--- 385,409 ---- X } X /* X * Here we fall through to vflush again to ensure X * that we have gotten rid of all the system vnodes. X */ X } X #endif X if (error = vflush(mp, NULLVP, flags)) X return (error); X fs = ump->um_fs; X! ronly = fs->fs_ronly; X! if ( ! ronly ) { X! fs->fs_clean = 1; X! sbupdate(ump,MNT_WAIT); X! } X ump->um_devvp->v_specflags &= ~SI_MOUNTEDON; X error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, X NOCRED, p); X vrele(ump->um_devvp); X free((caddr_t)fs->fs_csp[0], M_SUPERBLK); X free((caddr_t)fs, M_SUPERBLK); X free((caddr_t)ump, M_UFSMNT); X mp->mnt_data = (qaddr_t)0; X mp->mnt_flag &= ~MNT_LOCAL; X return (error); X*************** X*** 621,666 **** X * Write a superblock and associated information back to disk. X */ X sbupdate(mp, waitfor) X struct ufsmount *mp; X int waitfor; X { X register struct fs *fs = mp->um_fs; X register struct buf *bp; X int blks; X caddr_t space; X! int i, size, error = 0; X X bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); X bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); X /* Restore compatibility to old file systems. XXX */ X if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ X bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ X if (waitfor == MNT_WAIT) X error = bwrite(bp); X else X bawrite(bp); X blks = howmany(fs->fs_cssize, fs->fs_fsize); X space = (caddr_t)fs->fs_csp[0]; X for (i = 0; i < blks; i += fs->fs_frag) { X size = fs->fs_bsize; X if (i + fs->fs_frag > blks) X size = (blks - i) * fs->fs_fsize; X bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); X bcopy(space, bp->b_un.b_addr, (u_int)size); X space += size; X! if (waitfor == MNT_WAIT) X error = bwrite(bp); X! else X bawrite(bp); X } X! return (error); X } X X /* X * Print out statistics on the current allocation of the buffer pool. X * Can be enabled to print out on every ``sync'' by setting "syncprt" X * above. X */ X bufstats() X { X int s, i, j, count; X--- 634,684 ---- X * Write a superblock and associated information back to disk. X */ X sbupdate(mp, waitfor) X struct ufsmount *mp; X int waitfor; X { X register struct fs *fs = mp->um_fs; X register struct buf *bp; X int blks; X caddr_t space; X! int i, size, error, lasterror = 0; X X bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize); X bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize); X /* Restore compatibility to old file systems. XXX */ X if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */ X bp->b_un.b_fs->fs_nrpos = -1; /* XXX */ X if (waitfor == MNT_WAIT) X error = bwrite(bp); X else X bawrite(bp); X+ if (error) X+ lasterror=error; X blks = howmany(fs->fs_cssize, fs->fs_fsize); X space = (caddr_t)fs->fs_csp[0]; X for (i = 0; i < blks; i += fs->fs_frag) { X size = fs->fs_bsize; X if (i + fs->fs_frag > blks) X size = (blks - i) * fs->fs_fsize; X bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size); X bcopy(space, bp->b_un.b_addr, (u_int)size); X space += size; X! if (waitfor == MNT_WAIT) { X error = bwrite(bp); X! if (error) X! lasterror=error; X! } else { X bawrite(bp); X+ } X } X! return (lasterror); X } X X /* X * Print out statistics on the current allocation of the buffer pool. X * Can be enabled to print out on every ``sync'' by setting "syncprt" X * above. X */ X bufstats() X { X int s, i, j, count; X*** isofs/isofs_vfsops.c.orig Sat Jul 3 12:25:38 1993 X--- isofs/isofs_vfsops.c Sat Jul 3 12:26:26 1993 X*************** X*** 328,348 **** X */ X isofs_unmount(mp, mntflags, p) X struct mount *mp; X int mntflags; X struct proc *p; X { X register struct iso_mnt *isomp; X int i, error, ronly, flags = 0; X X if (mntflags & MNT_FORCE) { X! if (!iso_doforce || mp == rootfs) X return (EINVAL); X flags |= FORCECLOSE; X } X mntflushbuf(mp, 0); X if (mntinvalbuf(mp)) X return (EBUSY); X isomp = VFSTOISOFS(mp); X X if (error = vflush(mp, NULLVP, flags)) X return (error); X--- 328,348 ---- X */ X isofs_unmount(mp, mntflags, p) X struct mount *mp; X int mntflags; X struct proc *p; X { X register struct iso_mnt *isomp; X int i, error, ronly, flags = 0; X X if (mntflags & MNT_FORCE) { X! if (!iso_doforce) X return (EINVAL); X flags |= FORCECLOSE; X } X mntflushbuf(mp, 0); X if (mntinvalbuf(mp)) X return (EBUSY); X isomp = VFSTOISOFS(mp); X X if (error = vflush(mp, NULLVP, flags)) X return (error); X*** i386/i386/machdep.c.orig Sun Jul 11 16:13:50 1993 X--- i386/i386/machdep.c Sun Jul 11 16:13:48 1993 X*************** X*** 444,468 **** X--- 444,488 ---- X boot(arghowto) X int arghowto; X { X register long dummy; /* r12 is reserved */ X register int howto; /* r11 == how to boot */ X register int devtype; /* r10 == major of root dev */ X extern char *panicstr; X extern int cold; X int nomsg = 1; X X+ X+ /* X+ * cold apparently indicates that we haven't gotten far X+ * enough into the system to count on things working, therefore X+ * we just hang X+ */ X if(cold) { X printf("hit reset please"); X for(;;); X } X+ X+ /* X+ * delay 2 seconds before we actually do the halt. This is X+ * to give time for the floppy and/or other devices to shut down. X+ * DELAY says it does microseconds, but on MY machine, DELAY(1) X+ * appears to be *ten* microseconds. X+ */ X+ DELAY(200000); X+ X howto = arghowto; X+ X+ #if 0 X+ ! This code is superfluous because we already unmounted and synced X+ things from the system independent reboot(). X+ X if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) { X register struct buf *bp; X int iter, nbusy; X X waittime = 0; X (void) splnet(); X /* X * Release inodes held by texts before update. X */ X if (panicstr == 0) X*************** X*** 482,501 **** X--- 502,522 ---- X } X /* printf("%d ", nbusy); */ X DELAY(40000 * iter); X } X if (nbusy) X printf(" failed!\n"); X else if (nomsg == 0) X printf("succeded.\n"); X DELAY(10000); /* wait for printf to finish */ X } X+ #endif X splhigh(); X devtype = major(rootdev); X if (howto&RB_HALT) { X pg("\nThe operating system has halted. Please press any key to reboot.\n\n"); X } else { X if (howto & RB_DUMP) { X savectx(&dumppcb, 0); X dumppcb.pcb_ptd = rcr3(); X dumpsys(); X /*NOTREACHED*/ END-of-clean_kern.diff exit