*BSD News Article 21821


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