Subject: 'mount -o async' kernel support (finally) implemented (#331) Index: sys/sys/ 2.11BSD Description: The 'async' option of mount(8) was a NOP. While the option would be parsed and the flag passed to the kernel there was no code in the kernel which paid attention to it. Specifying the O_FSYNC flag to open(2) did not have any effect. Repeat-By: Observation. Mention was made earlier (in the updates which dealt with fstab(5), mount(8)) that the 'MNT_ASYNC' (-o async) flag was set/cleared but not used. Another method is to time the creation and removal of a directory tree. With 'async' updates enabled the elapsed time for operations such as copying, removing or creating directory hierarchies is dramatically reduced. Fix: NOTE: the "-o async" option to mount(8) should *NEVER* be used on any filesystem you are not prepared to reload if the system should crash or suffer a power failure. Filesystems using async updates *may* be damaged/corrupted beyond fsck(8)'s ability to repair if critical filesystem updates are pending when the power goes out. Async updates do not permanently defer inode/superblock updates. The updates are only delayed until the next sync(2) system call is done (or the filesystem is unmounted). Update(8) issues a sync(2) every 30 seconds. When would 'async' updates be useful? /tmp being on a partition of its own is one case. This is what the fstab(5) entry would look like: /dev/ra0e /tmp ufs rw,async 1 3 Another *real good* use of '-o async' is when copying or removing large directory hierarchies. The common method of doing this is with a tar pipeline: (cd /foo; tar -cf - .) | (cd /bar; tar -xpf -) In this case you would want to turn on the 'async' flag before doing the copy and then turn off the 'async' flag when the copy is done. This is possible using the 'update' option to mount(8): mount -u -o async /bar (cd /foo; tar -cf - .) | (cd /bar; tar -xpf -) mount -u -o noasync /bar Removing deep directory trees is another good time to use async updates. If, for example you have a scratch copy of /usr stored in /bar as /bar/usr and now it is time to delete /bar/usr: mount -u -o async /bar rm -r /bar/usr mount -u -o noasync /bar The changes to the kernel are moderately large. Many of the modifications are small but there are numerous places that needed changing. A couple kernel functions take a different number of arguments now, itrunc() takes 3 args rather than two for example. A couple kernel function names have changed. The function which allocates a block of diskspace is now called 'balloc' rather than simply 'alloc'. This is, I believe more meaningful as it describes what is being allocated. The largest single change was in the 'sync' handling. The kernel function which handles the sync call is now called 'sync()' rather than 'update()'. It always struck me as silly to call the routine update() but then put in a comment saying it's effectively 'sync()'. The inner loop from sync() was moved to a new function 'ufs_sync' so that a single filesystem can be sync'd. The 'unmount' processing now calls 'ufs_sync()' rather than 'update()' - this way only the filesystem being unmounted gets sync'd rather than all filesystems. The O_FSYNC flag to open(2) now turns on the IO_SYNC flag which is passed to the lower level block I/O routines. Applications can now request synchronous I/O on a per file basis. NOTE: If the system administrator turns on the 'async' mount flag that overrides O_FSYNC. How effective are 'async updates'? That depends in part on the type of disk drive being used. Older, slower drives (such as the RD54) show a *dramatic* decrease (50% in some cases) in elapsed time for removing many files from directories. Newer, faster drives (which often include a cache in the drive) show a less dramatic results but the decrease in elapsed time is still in the realm of 20%. There were two simple tests used to demonstrate the effectiveness of async updates. The first creates a large directory hierarchy using "mkdir -p". find /usr -type d -print | sed -e "s,^,mkdir -p /mnt," > /tmp/dir First we mount the scratch filesystem normally (no async updates): mount /dev/ra8g /mnt Then run the two timed tests: time sh /tmp/dir time rm -r /mnt/usr Using an RD54 the result was: sh /tmp/dir: 33.8u 149.4s 6:24 47% 1539+4462io rm -r: 1.7u 53.8s 3:17 28% 797+2270io Next update the mount flags, turning on the 'async update' mode: mount -u -o async /mnt time sh /tmp/dir time rm -r /mnt/usr sh /tmp/dir: 33.3u 105.5s 2:51 81% 300+2148io rm -r: 2.1u 48.7s 1:21 62% 788+801io Quite a difference, eh? From 6min24sec to 2min51sec when creating the directory hierarchy and from 3min17sec to 1min21sec when removing it. How does performing 'async updates' cause such a marked improvement? When a directory is updated the kernel normally writes out the modified block of the directory synchronously. If multiple files/directories are being created then the modified directory block(s) get written out for each file created - if a directory is populated with 10 files then the directory is updated 10 times. By performing the filesystem updates 'asynchronously' (letting 'update' do the "sync" once every 30 seconds) the modified directory block(s) are left in the buffer cache and _not_ written out multiple times. Async updates also defer writing out modified inodes until a 'sync' is performed. Thus if a file is accessed repeatedly (causing the timestamps in the inode to be updated) the inode is not written out to disk multiple times. Oh, for more modern disks which have a lower seek time as well as an onboard cache the decrease in elapsed times is closer to 20% rather than 50 or 60%. For an HP3724S (1.2GB, 9.5ms seek, 512kb cache) the numbers from the tests above are: no async -------- sh /tmp/dir: 33.0u 112.6s 3:04 78% 719+4450io rm -r: 2.4u 52.8s 1:24 65% 790+2258io async ----- sh /tmp/dir: 33.8u 104.9s 2:35 89% 315+2140io rm -r: 2.7u 48.6s 1:08 75% 790+804io And with out further ado here is how to install the update. NOTE: you may or may not have to adjust the kernel overlay configuration. The changes in object sizes are slight but may be enough, as they were in the case of the GENERIC kernel, to cause overlays or the base segment to be too large. The patch below adjusts the GENERIC Makefile. Other kernel config files may need to be edited manually. Cut where indicated, saving to a file (/tmp/331). Then: cd /tmp patch -p0 < 331 cd /sys/YOUR_KERNEL make clean make mv /unix /ounix mv /netnix /onetnix mv unix netnix / chmod 744 /unix /netnix reboot It is a good idea to have a GENERIC kernel around. I keep a copy in /genunix. cd /sys/GENERIC make clean make mv unix /genunix make clean This and previous updates, as always, are available via anonyous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the directory /put/2.11BSD. ----------------------------cut here------------------------ *** /usr/src/sys/h/buf.h.old Sun Jun 9 20:07:10 1996 --- /usr/src/sys/h/buf.h Sat Sep 14 20:38:35 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)buf.h 1.3 (2.11BSD GTE) 1996/6/9 */ /* --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)buf.h 1.4 (2.11BSD GTE) 1996/9/13 */ /* *************** *** 68,73 **** --- 68,77 ---- #define BQ_AGE 2 /* rubbish */ #define BQ_EMPTY 3 /* buffer headers with no memory */ + /* Flags to low-level allocation routines. */ + #define B_CLRBUF 0x01 /* Request allocated buffer be cleared. */ + #define B_SYNC 0x02 /* Do all allocations synchronously. */ + #define bawrite(bp) {(bp)->b_flags |= B_ASYNC; bwrite(bp);} #define bfree(bp) (bp)->b_bcount = 0 #define bftopaddr(bp) ((u_int)(bp)->b_un.b_addr >> 6 | (bp)->b_xmem << 10) *************** *** 80,86 **** extern struct bufhd bufhash[]; /* heads of hash lists */ extern struct buf bfreelist[]; /* heads of available lists */ ! struct buf *alloc(); struct buf *getblk(); struct buf *geteblk(); struct buf *getnewbuf(); --- 84,90 ---- extern struct bufhd bufhash[]; /* heads of hash lists */ extern struct buf bfreelist[]; /* heads of available lists */ ! struct buf *balloc(); struct buf *getblk(); struct buf *geteblk(); struct buf *getnewbuf(); *** /usr/src/sys/pdp/machdep2.c.old Sun Dec 24 12:39:33 1995 --- /usr/src/sys/pdp/machdep2.c Sat Sep 14 21:28:49 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)machdep2.c 2.6 (2.11BSD GTE) 1995/12/24 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)machdep2.c 2.7 (2.11BSD GTE) 1996/9/14 */ #include "param.h" *************** *** 398,404 **** * Release inodes held by texts before update. */ xumount(NODEV); ! update(); { register struct buf *bp; int iter, nbusy; --- 398,404 ---- * Release inodes held by texts before update. */ xumount(NODEV); ! sync(); { register struct buf *bp; int iter, nbusy; *** /usr/src/sys/sys/kern_acct.c.old Sat Nov 26 23:08:26 1994 --- /usr/src/sys/sys/kern_acct.c Mon Sep 16 21:09:07 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)kern_acct.c 2.2 (2.11BSD) 11/26/94 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)kern_acct.c 2.3 (2.11BSD) 1996/9/13 */ #include "param.h" *************** *** 136,142 **** u.u_error = rdwri(UIO_WRITE, ip, ap, sizeof(acctbuf), siz, UIO_SYSSPACE, IO_UNIT|IO_APPEND, (int *)0); if (u.u_error) ! itrunc(ip, (u_long)siz); iunlock(ip); } --- 136,142 ---- u.u_error = rdwri(UIO_WRITE, ip, ap, sizeof(acctbuf), siz, UIO_SYSSPACE, IO_UNIT|IO_APPEND, (int *)0); if (u.u_error) ! itrunc(ip, (u_long)siz, 0); iunlock(ip); } *** /usr/src/sys/sys/kern_sig.c.old Sat Nov 26 23:16:37 1994 --- /usr/src/sys/sys/kern_sig.c Mon Sep 16 21:06:27 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)kern_sig.c 1.5 (2.11BSD GTE) 11/26/94 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)kern_sig.c 1.6 (2.11BSD GTE) 1996/9/13 */ #include "param.h" *************** *** 838,844 **** u.u_error = EFAULT; goto out; } ! itrunc(ip, (u_long)0); u.u_acflag |= ACORE; u.u_error = rdwri(UIO_WRITE, ip, &u, ctob(USIZE), (off_t)0, UIO_SYSSPACE, IO_UNIT, (int *)0); --- 838,844 ---- u.u_error = EFAULT; goto out; } ! itrunc(ip, (u_long)0, 0); u.u_acflag |= ACORE; u.u_error = rdwri(UIO_WRITE, ip, &u, ctob(USIZE), (off_t)0, UIO_SYSSPACE, IO_UNIT, (int *)0); *** /usr/src/sys/sys/sys_inode.c.old Sat Mar 2 00:45:38 1996 --- /usr/src/sys/sys/sys_inode.c Thu Sep 19 20:57:44 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)sys_inode.c 1.7 (2.11BSD GTE) 1996/3/2 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)sys_inode.c 1.8 (2.11BSD GTE) 1996/9/19 */ #include "param.h" *************** *** 56,61 **** --- 56,64 ---- ioflag |= IO_APPEND; if (fp->f_flag & FNONBLOCK) ioflag |= IO_NDELAY; + if (fp->f_flag & FFSYNC || + (ip->i_fs->fs_flags & MNT_SYNCHRONOUS)) + ioflag |= IO_SYNC; error = rwip(ip, uio, ioflag); if (ioflag & IO_APPEND) fp->f_offset = uio->uio_offset; *************** *** 109,114 **** --- 112,118 ---- daddr_t lbn, bn; int n, on, type, resid; int error = 0; + int flags; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) *************** *** 152,157 **** --- 156,176 ---- } } + /* + * The IO_SYNC flag is turned off here if the 'async' mount flag is on. + * Otherwise directory I/O (which is done by the kernel) would still + * synchronous (because the kernel carefully passes IO_SYNC for all directory + * I/O) even if the fs was mounted with "-o async". + * + * A side effect of this is that if the system administrator mounts a filesystem + * 'async' then the O_FSYNC flag to open() is ignored. + * + * This behaviour should probably be selectable via "sysctl fs.async.dirs" and + * "fs.async.ofsync". A project for a rainy day. + */ + if (type == IFREG || type == IFDIR && (ip->i_fs->fs_flags & MNT_ASYNC)) + ioflag &= ~IO_SYNC; + if (type == IFCHR) { if (uio->uio_rw == UIO_READ) error = (*cdevsw[major(dev)].d_read)(dev, uio, ioflag); *************** *** 194,199 **** --- 213,220 ---- resid = uio->uio_resid; osize = ip->i_size; + flags = ioflag & IO_SYNC ? B_SYNC : 0; + do { lbn = lblkno(uio->uio_offset); on = blkoff(uio->uio_offset); *************** *** 205,214 **** return (0); if (diff < n) n = diff; ! bn = bmap(ip, lbn, B_READ, 0); } else ! bn = bmap(ip,lbn,B_WRITE,n == DEV_BSIZE ? 0: 1); if (u.u_error || uio->uio_rw == UIO_WRITE && (long)bn<0) return (u.u_error); if (uio->uio_rw == UIO_WRITE && uio->uio_offset + n > ip->i_size && --- 226,236 ---- return (0); if (diff < n) n = diff; ! bn = bmap(ip, lbn, B_READ, flags); } else ! bn = bmap(ip,lbn,B_WRITE, ! n == DEV_BSIZE ? flags : flags|B_CLRBUF); if (u.u_error || uio->uio_rw == UIO_WRITE && (long)bn<0) return (u.u_error); if (uio->uio_rw == UIO_WRITE && uio->uio_offset + n > ip->i_size && *************** *** 260,265 **** --- 282,294 ---- } else { if (ioflag & IO_SYNC) bwrite(bp); + /* + * The check below interacts _very_ badly with virtual memory tmp files + * such as those used by 'ld'. These files tend to be small and repeatedly + * rewritten in 1kb chunks. The check below causes the device driver to be + * called (and I/O initiated) constantly. Not sure what to do about this yet + * but this comment is being placed here as a reminder. + */ else if (n + on == DEV_BSIZE && !(ip->i_flag & IPIPE)) { bp->b_flags |= B_AGE; bawrite(bp); *************** *** 274,280 **** error = u.u_error; /* XXX */ if (error && (uio->uio_rw == UIO_WRITE) && (ioflag & IO_UNIT) && (type != IFBLK)) { ! itrunc(ip, osize); uio->uio_offset -= (resid - uio->uio_resid); uio->uio_resid = resid; /* --- 303,309 ---- error = u.u_error; /* XXX */ if (error && (uio->uio_rw == UIO_WRITE) && (ioflag & IO_UNIT) && (type != IFBLK)) { ! itrunc(ip, osize, ioflag & IO_SYNC); uio->uio_offset -= (resid - uio->uio_resid); uio->uio_resid = resid; /* *** /usr/src/sys/sys/ufs_alloc.c.old Wed Jan 11 20:07:49 1995 --- /usr/src/sys/sys/ufs_alloc.c Thu Sep 19 21:49:24 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_alloc.c 1.2 (2.11BSD GTE) 1/11/94 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_alloc.c 1.3 (2.11BSD GTE) 1996/9/19 */ #include "param.h" *************** *** 15,20 **** --- 15,21 ---- #include "buf.h" #include "user.h" #include "kernel.h" + #include "mount.h" #ifdef QUOTA #include "quota.h" #endif *************** *** 30,44 **** * obtain NICFREE more... */ struct buf * ! alloc(ip, clrflg) struct inode *ip; ! int clrflg; { register struct fs *fs; register struct buf *bp; daddr_t bno; fs = ip->i_fs; while (fs->fs_flock) sleep((caddr_t)&fs->fs_flock, PINOD); do { --- 31,48 ---- * obtain NICFREE more... */ struct buf * ! balloc(ip, flags) struct inode *ip; ! int flags; { register struct fs *fs; register struct buf *bp; + int async; daddr_t bno; fs = ip->i_fs; + async = fs->fs_flags & MNT_ASYNC; + while (fs->fs_flock) sleep((caddr_t)&fs->fs_flock, PINOD); do { *************** *** 64,70 **** } brelse(bp); /* ! * Write the superblock back, synchronously, * so that the free list pointer won't point at garbage. * We can still end up with dups in free if we then * use some of the blocks in this freeblock, then crash --- 68,74 ---- } brelse(bp); /* ! * Write the superblock back, synchronously if requested, * so that the free list pointer won't point at garbage. * We can still end up with dups in free if we then * use some of the blocks in this freeblock, then crash *************** *** 80,86 **** *fps = *fs; } mapout(bp); ! bwrite(bp); fs->fs_flock = 0; wakeup((caddr_t)&fs->fs_flock); if (fs->fs_nfree <=0) --- 84,93 ---- *fps = *fs; } mapout(bp); ! if (!async) ! bwrite(bp); ! else ! bdwrite(bp); fs->fs_flock = 0; wakeup((caddr_t)&fs->fs_flock); if (fs->fs_nfree <=0) *************** *** 88,94 **** } bp = getblk(ip->i_dev, bno); bp->b_resid = 0; ! if (clrflg) clrbuf(bp); fs->fs_fmod = 1; fs->fs_tfree--; --- 95,101 ---- } bp = getblk(ip->i_dev, bno); bp->b_resid = 0; ! if (flags & B_CLRBUF) clrbuf(bp); fs->fs_fmod = 1; fs->fs_tfree--; *************** *** 220,226 **** if (fs->fs_ninode > 0) goto loop; fserr(fs, emsg); ! uprintf("\n%s: create/symlink failed, %s\n", fs->fs_fsmnt, emsg); u.u_error = ENOSPC; return(NULL); } --- 227,233 ---- if (fs->fs_ninode > 0) goto loop; fserr(fs, emsg); ! uprintf("\n%s: %s\n", fs->fs_fsmnt, emsg); u.u_error = ENOSPC; return(NULL); } *************** *** 257,263 **** *fbp = *((FBLKP)&fs->fs_nfree); mapout(bp); fs->fs_nfree = 0; ! bwrite(bp); fs->fs_flock = 0; wakeup((caddr_t)&fs->fs_flock); } --- 264,273 ---- *fbp = *((FBLKP)&fs->fs_nfree); mapout(bp); fs->fs_nfree = 0; ! if (fs->fs_flags & MNT_ASYNC) ! bdwrite(bp); ! else ! bwrite(bp); fs->fs_flock = 0; wakeup((caddr_t)&fs->fs_flock); } *** /usr/src/sys/sys/ufs_bio.c.old Sun Jan 3 00:45:09 1993 --- /usr/src/sys/sys/ufs_bio.c Thu Sep 19 19:59:36 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_bio.c 2.1 (2.11BSD) 12/26/92 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_bio.c 2.2 (2.11BSD) 1996/9/13 */ #include "param.h" *************** *** 325,332 **** bp = dp->av_forw; notavail(bp); if (bp->b_flags & B_DELWRI) { ! bp->b_flags |= B_ASYNC; ! bwrite(bp); goto loop; } if(bp->b_flags & (B_RAMREMAP|B_PHYS)) { --- 325,331 ---- bp = dp->av_forw; notavail(bp); if (bp->b_flags & B_DELWRI) { ! bawrite(bp); goto loop; } if(bp->b_flags & (B_RAMREMAP|B_PHYS)) { *************** *** 421,430 **** } /* ! * Make sure all write-behind blocks ! * on dev (or NODEV for all) ! * are flushed out. ! * (from umount and update) */ bflush(dev) register dev_t dev; --- 420,427 ---- } /* ! * Make sure all write-behind blocks on dev are flushed out. ! * (from umount and sync) */ bflush(dev) register dev_t dev; *************** *** 439,445 **** for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) { if ((bp->b_flags & B_DELWRI) == 0) continue; ! if (dev == NODEV || dev == bp->b_dev) { bp->b_flags |= B_ASYNC; notavail(bp); bwrite(bp); --- 436,442 ---- for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) { if ((bp->b_flags & B_DELWRI) == 0) continue; ! if (dev == bp->b_dev) { bp->b_flags |= B_ASYNC; notavail(bp); bwrite(bp); *** /usr/src/sys/sys/ufs_bmap.c.old Sun Apr 8 03:03:57 1990 --- /usr/src/sys/sys/ufs_bmap.c Thu Sep 19 21:51:20 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_bmap.c 1.1 (2.10BSD Berkeley) 12/1/86 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_bmap.c 1.2 (2.11BSD) 1996/9/19 */ #include "param.h" *************** *** 16,21 **** --- 16,22 ---- #include "user.h" #include "buf.h" #include "fs.h" + #include "mount.h" #include "uio.h" /* *************** *** 27,36 **** * for use in read-ahead. */ daddr_t ! bmap(ip, bn, rwflg, clrflg) register struct inode *ip; daddr_t bn; ! int rwflg, clrflg; { register int i; register struct buf *bp; --- 28,37 ---- * for use in read-ahead. */ daddr_t ! bmap(ip, bn, rwflg, flags) register struct inode *ip; daddr_t bn; ! int rwflg, flags; { register int i; register struct buf *bp; *************** *** 37,42 **** --- 38,44 ---- struct buf *nbp; int j, sh; daddr_t nb, *bap, ra; + int async = ip->i_fs->fs_flags & MNT_ASYNC; if (bn < 0) { u.u_error = EFBIG; *************** *** 51,65 **** i = bn; nb = ip->i_addr[i]; if (nb == 0) { ! if (rwflg == B_READ || (bp = alloc(ip, clrflg)) == NULL) return((daddr_t)-1); nb = dbtofsb(bp->b_blkno); ! if ((ip->i_mode&IFMT) == IFDIR) ! /* ! * Write directory blocks synchronously ! * so they never appear with garbage in ! * them on the disk. ! */ bwrite(bp); else bdwrite(bp); --- 53,67 ---- i = bn; nb = ip->i_addr[i]; if (nb == 0) { ! if (rwflg == B_READ || (bp = balloc(ip, flags)) == NULL) return((daddr_t)-1); nb = dbtofsb(bp->b_blkno); ! /* ! * directory blocks are usually the only thing written synchronously at this ! * point (so they never appear with garbage in them on the disk). This is ! * overridden if the filesystem was mounted 'async'. ! */ ! if (flags & B_SYNC) bwrite(bp); else bdwrite(bp); *************** *** 97,110 **** */ nb = ip->i_addr[NADDR-j]; if (nb == 0) { ! if (rwflg == B_READ || (bp = alloc(ip, 1)) == NULL) return((daddr_t) -1); nb = dbtofsb(bp->b_blkno); /* ! * Write synchronously so that indirect blocks * never point at garbage. */ ! bwrite(bp); ip->i_addr[NADDR-j] = nb; ip->i_flag |= IUPD|ICHG; } --- 99,115 ---- */ nb = ip->i_addr[NADDR-j]; if (nb == 0) { ! if (rwflg == B_READ || (bp = balloc(ip, flags | B_CLRBUF)) == NULL) return((daddr_t) -1); nb = dbtofsb(bp->b_blkno); /* ! * Write synchronously if requested so that indirect blocks * never point at garbage. */ ! if (async) ! bdwrite(bp); ! else ! bwrite(bp); ip->i_addr[NADDR-j] = nb; ip->i_flag |= IUPD|ICHG; } *************** *** 129,145 **** ra = bap[i+1]; mapout(bp); if (nb == 0) { ! if (rwflg == B_READ || (nbp = alloc(ip, 1)) == NULL) { brelse(bp); return((daddr_t) -1); } nb = dbtofsb(nbp->b_blkno); ! if (j < 3 || (ip->i_mode&IFMT) == IFDIR) ! /* ! * Write synchronously so indirect blocks ! * never point at garbage and blocks ! * in directories never contain garbage. ! */ bwrite(nbp); else bdwrite(nbp); --- 134,151 ---- ra = bap[i+1]; mapout(bp); if (nb == 0) { ! if (rwflg == B_READ || (nbp = balloc(ip, flags | B_CLRBUF)) == NULL) { brelse(bp); return((daddr_t) -1); } nb = dbtofsb(nbp->b_blkno); ! /* ! * Write synchronously so indirect blocks never point at garbage and blocks ! * in directories never contain garbage. This check used to be based on the ! * type of inode, if it was a directory then 'sync' writes were done. See the ! * comments earlier about filesystems being mounted 'async'. ! */ ! if (!async && (j < 3 || (flags & B_SYNC))) bwrite(nbp); else bdwrite(nbp); *** /usr/src/sys/sys/ufs_fio.c.old Thu Dec 29 17:31:03 1994 --- /usr/src/sys/sys/ufs_fio.c Mon Sep 16 21:09:30 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_fio.c 1.3 (2.11BSD GTE) 12/29/94 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_fio.c 1.4 (2.11BSD GTE) 1996/9/13 */ #include "param.h" *************** *** 162,168 **** { if ((ip->i_mode & IFMT) == IFDIR) return(EISDIR); ! itrunc(ip, vap->va_size); if (u.u_error) return(u.u_error); } --- 162,168 ---- { if ((ip->i_mode & IFMT) == IFDIR) return(EISDIR); ! itrunc(ip, vap->va_size, 0); if (u.u_error) return(u.u_error); } *** /usr/src/sys/sys/ufs_inode.c.old Mon Nov 28 20:33:32 1994 --- /usr/src/sys/sys/ufs_inode.c Thu Sep 19 21:23:28 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_inode.c 1.4 (2.11BSD GTE) 11/26/94 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_inode.c 1.5 (2.11BSD GTE) 1996/9/19 */ #include "param.h" *************** *** 312,322 **** if (ip->i_count == 1) { ip->i_flag |= ILOCKED; if (ip->i_nlink <= 0 && ip->i_fs->fs_ronly == 0) { - itrunc(ip, (u_long)0); - ip->i_mode = 0; - ip->i_rdev = 0; - ip->i_flag |= IUPD|ICHG; - ifree(ip, ip->i_number); #ifdef QUOTA QUOTAMAP(); (void) chkiq(ip->i_dev, ip, ip->i_uid, 0); --- 312,317 ---- *************** *** 324,329 **** --- 319,329 ---- ix_dquot[ip - inode] = NODQUOT; QUOTAUNMAP(); #endif + itrunc(ip, (u_long)0, 0); + ip->i_mode = 0; + ip->i_rdev = 0; + ip->i_flag |= IUPD|ICHG; + ifree(ip, ip->i_number); } IUPDAT(ip, &time, &time, 0); IUNLOCK(ip); *************** *** 411,417 **** #endif bcopy(ip->i_addr, dp->di_addr, NADDR * sizeof (daddr_t)); mapout(bp); ! if (waitfor) bwrite(bp); else bdwrite(bp); --- 411,417 ---- #endif bcopy(ip->i_addr, dp->di_addr, NADDR * sizeof (daddr_t)); mapout(bp); ! if (waitfor && ((ip->i_fs->fs_flags & MNT_ASYNC) == 0)) bwrite(bp); else bdwrite(bp); *************** *** 428,436 **** * * NB: triple indirect blocks are untested. */ ! itrunc(oip,length) register struct inode *oip; u_long length; { daddr_t lastblock; register int i; --- 428,437 ---- * * NB: triple indirect blocks are untested. */ ! itrunc(oip,length, ioflags) register struct inode *oip; u_long length; + int ioflags; { daddr_t lastblock; register int i; *************** *** 439,448 **** --- 440,454 ---- struct buf *bp; int offset, level; struct inode tip; + int aflags; #ifdef QUOTA long bytesreleased; #endif + aflags = B_CLRBUF; + if (ioflags & IO_SYNC) + aflags |= B_SYNC; + /* * special hack for pipes, since size for them isn't the size of * the file, it's the amount currently waiting for transfer. It's *************** *** 452,462 **** */ if (oip->i_flag & IPIPE) oip->i_size = MAXPIPSIZ; ! else if (oip->i_size <= length) { ! oip->i_flag |= ICHG|IUPD; ! iupdat(oip, &time, &time, 1); ! return; } /* * Calculate index into inode's block list of * last direct and indirect blocks (if any) --- 458,483 ---- */ if (oip->i_flag & IPIPE) oip->i_size = MAXPIPSIZ; ! else if (oip->i_size == length) ! goto updret; ! ! /* ! * Lengthen the size of the file. We must ensure that the ! * last byte of the file is allocated. Since the smallest ! * value of osize is 0, length will be at least 1. ! */ ! if (oip->i_size < length) { ! bn = bmap(oip, lblkno(length - 1), B_WRITE, aflags); ! if (u.u_error || bn < 0) ! return; ! #ifdef QUOTA ! bytesreleased = oip->i_size - length; ! #endif ! oip->i_size = length; ! bdwrite(bp); ! goto doquotaupd; } + /* * Calculate index into inode's block list of * last direct and indirect blocks (if any) *************** *** 476,482 **** */ offset = blkoff(length); if (offset) { ! bn = bmap(oip, lblkno(length), B_WRITE, 1); if (u.u_error || bn < 0) return; bp = bread(oip->i_dev, bn); --- 497,503 ---- */ offset = blkoff(length); if (offset) { ! bn = bmap(oip, lblkno(length), B_WRITE, aflags); if (u.u_error || bn < 0) return; bp = bread(oip->i_dev, bn); *************** *** 509,516 **** } for (i = NDADDR - 1; i > lastblock; i--) oip->i_db[i] = 0; - oip->i_flag |= ICHG|IUPD; - iupdat(oip, &time, &time, 1); /* * Indirect blocks first. --- 530,535 ---- *************** *** 519,525 **** for (level = TRIPLE; level >= SINGLE; level--) { bn = ip->i_ib[level]; if (bn != 0) { ! indirtrunc(ip, bn, lastiblock[level], level); if (lastiblock[level] < 0) { ip->i_ib[level] = 0; free(ip, bn); --- 538,544 ---- for (level = TRIPLE; level >= SINGLE; level--) { bn = ip->i_ib[level]; if (bn != 0) { ! indirtrunc(ip, bn, lastiblock[level], level, aflags); if (lastiblock[level] < 0) { ip->i_ib[level] = 0; free(ip, bn); *************** *** 553,564 **** panic("itrunc2"); /* END PARANOIA */ #endif ! oip->i_flag |= ICHG; #ifdef QUOTA QUOTAMAP(); (void)chkdq(oip, -bytesreleased, 0); QUOTAUNMAP(); #endif } /* --- 572,587 ---- panic("itrunc2"); /* END PARANOIA */ #endif ! ! doquotaupd: #ifdef QUOTA QUOTAMAP(); (void)chkdq(oip, -bytesreleased, 0); QUOTAUNMAP(); #endif + updret: + oip->i_flag |= ICHG|IUPD; + iupdat(oip, &time, &time, 1); } /* *************** *** 571,580 **** * * NB: triple indirect blocks are untested. */ ! indirtrunc(ip, bn, lastbn, level) struct inode *ip; daddr_t bn, lastbn; int level; { register struct buf *bp; daddr_t nb, last; --- 594,604 ---- * * NB: triple indirect blocks are untested. */ ! indirtrunc(ip, bn, lastbn, level, aflags) struct inode *ip; daddr_t bn, lastbn; int level; + int aflags; { register struct buf *bp; daddr_t nb, last; *************** *** 619,625 **** bzero((caddr_t)&bap[last + 1], (u_int)(NINDIR - (last + 1)) * sizeof(daddr_t)); mapout(bp); ! bwrite(bp); bp = cpy; } --- 643,652 ---- bzero((caddr_t)&bap[last + 1], (u_int)(NINDIR - (last + 1)) * sizeof(daddr_t)); mapout(bp); ! if (aflags & B_SYNC) ! bwrite(bp); ! else ! bawrite(bp); bp = cpy; } *************** *** 632,638 **** * and that doesn't work well with recursion. */ if (level == SINGLE) ! trsingle(ip, bp, last); else { register daddr_t *bstart, *bstop; --- 659,665 ---- * and that doesn't work well with recursion. */ if (level == SINGLE) ! trsingle(ip, bp, last, aflags); else { register daddr_t *bstart, *bstop; *************** *** 646,652 **** nb = *bstart; if (nb) { mapout(bp); ! indirtrunc(ip, nb, (daddr_t)-1, level - 1); free(ip, nb); mapin(bp); } --- 673,679 ---- nb = *bstart; if (nb) { mapout(bp); ! indirtrunc(ip,nb,(daddr_t)-1, level-1, aflags); free(ip, nb); mapin(bp); } *************** *** 663,669 **** mapout(bp); last = lastbn % factor; if (nb != 0) ! indirtrunc(ip, nb, last, level - 1); } } brelse(bp); --- 690,696 ---- mapout(bp); last = lastbn % factor; if (nb != 0) ! indirtrunc(ip, nb, last, level - 1, aflags); } } brelse(bp); *************** *** 670,679 **** } static ! trsingle(ip, bp,last) register struct inode *ip; caddr_t bp; daddr_t last; { register daddr_t *bstart, *bstop; daddr_t blarray[NINDIR]; --- 697,707 ---- } static ! trsingle(ip, bp,last, aflags) register struct inode *ip; caddr_t bp; daddr_t last; + int aflags; { register daddr_t *bstart, *bstop; daddr_t blarray[NINDIR]; *** /usr/src/sys/sys/ufs_mount.c.old Sat Apr 20 21:56:21 1996 --- /usr/src/sys/sys/ufs_mount.c Mon Sep 16 21:24:08 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_mount.c 1.8 (2.11BSD GTE) 1996/4/20 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_mount.c 1.9 (2.11BSD GTE) 1996/9/13 */ #include "param.h" *************** *** 270,275 **** --- 270,276 ---- register struct mount *mp; register struct inode *ip; register int error; + int aflag; error = getmdev(&dev, fname); if (error) *************** *** 281,293 **** found: xumount(dev); /* remove unused sticky files from text table */ nchinval(dev); /* flush the name cache */ ! update(); #ifdef QUOTA if (iflush(dev, mp->m_qinod) < 0) #else if (iflush(dev) < 0) #endif return (EBUSY); #ifdef QUOTA QUOTAMAP(); closedq(mp); --- 282,300 ---- found: xumount(dev); /* remove unused sticky files from text table */ nchinval(dev); /* flush the name cache */ ! aflag = mp->m_flags & MNT_ASYNC; ! mp->m_flags &= ~MNT_ASYNC; /* Don't want async when unmounting */ ! ufs_sync(mp); ! #ifdef QUOTA if (iflush(dev, mp->m_qinod) < 0) #else if (iflush(dev) < 0) #endif + { + mp->m_flags |= aflag; return (EBUSY); + } #ifdef QUOTA QUOTAMAP(); closedq(mp); *** /usr/src/sys/sys/ufs_namei.c.old Sat Nov 26 23:26:42 1994 --- /usr/src/sys/sys/ufs_namei.c Mon Sep 16 21:08:35 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_namei.c 1.3 (2.11BSD GTE) 11/26/94 */ #include "param.h" #include "../machine/seg.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_namei.c 1.4 (2.11BSD GTE) 1996/9/13 */ #include "param.h" #include "../machine/seg.h" *************** *** 984,990 **** bwrite(bp); dp->i_flag |= IUPD|ICHG; if (ndp->ni_endoff && ndp->ni_endoff < dp->i_size) ! itrunc(dp, (u_long)ndp->ni_endoff); iput(dp); return (error); } --- 984,990 ---- bwrite(bp); dp->i_flag |= IUPD|ICHG; if (ndp->ni_endoff && ndp->ni_endoff < dp->i_size) ! itrunc(dp, (u_long)ndp->ni_endoff, 0); iput(dp); return (error); } *** /usr/src/sys/sys/ufs_subr.c.old Wed Feb 16 19:39:05 1994 --- /usr/src/sys/sys/ufs_subr.c Mon Sep 16 21:08:51 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_subr.c 1.4 (2.11BSD GTE) 2/15/94 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_subr.c 1.5 (2.11BSD GTE) 1996/9/13 */ #include "param.h" *************** *** 19,89 **** #include "systm.h" /* ! * Update is the internal name of 'sync'. It goes through the disk ! * queues to initiate sandbagged IO; goes through the inodes to write ! * modified nodes; and it goes through the mount table to initiate ! * the writing of the modified super blocks. */ ! update() { register struct mount *mp; ! register struct buf *bp; ! if (updlock) return; updlock++; ! /* ! * Write back modified superblocks. ! * Consistency check that the superblock ! * of each file system is still in the buffer cache. ! */ ! for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { ! register struct fs *fs; ! ! if (mp->m_inodp == NULL || mp->m_dev == NODEV) continue; fs = &mp->m_filsys; ! if (fs->fs_fmod == 0) continue; ! if (fs->fs_ronly != 0) { /* XXX */ ! printf("fs = %s\n", fs->fs_fsmnt); ! panic("update: rofs mod"); } ! if (fs->fs_ilock || fs->fs_flock) ! continue; ! bp = getblk(mp->m_dev, SUPERB); ! if (bp->b_flags & B_ERROR) ! continue; ! fs->fs_fmod = 0; ! fs->fs_time = time.tv_sec; ! bcopy(fs, mapin(bp), sizeof (struct fs)); ! mapout(bp); ! bwrite(bp); } - /* - * Write back each (modified) inode. - */ - { - register struct inode *ip; - for (ip = inode; ip < inodeNINODE; ip++) { - if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0 || - (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0) - continue; - ip->i_flag |= ILOCKED; - ip->i_count++; - iupdat(ip, &time, &time, 0); - iput(ip); - } - } - updlock = 0; - /* - * Force stale buffer cache information to be flushed, - * for all devices. - */ - bflush(NODEV); - } - /* * Flush all the blocks associated with an inode. * There are two strategies based on the size of the file; --- 19,52 ---- #include "systm.h" /* ! * Go through the mount table looking for filesystems which have been modified. ! * For each "dirty" filesystem call 'ufs_sync' to flush changed inodes, data ! * blocks and the superblock to disc. */ ! sync() { register struct mount *mp; ! register struct fs *fs; ! int async; ! if (updlock) return; updlock++; ! for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) ! { ! if (mp->m_inodp == NULL || mp->m_dev == NODEV) continue; fs = &mp->m_filsys; ! if (fs->fs_fmod == 0 || fs->fs_ilock || fs->fs_flock) continue; ! async = mp->m_flags & MNT_ASYNC; ! mp->m_flags &= ~MNT_ASYNC; ! ufs_sync(mp); ! mp->m_flags |= async; } ! updlock = 0; } /* * Flush all the blocks associated with an inode. * There are two strategies based on the size of the file; *************** *** 207,239 **** if (mp->m_dev == dev) return (mp - &mount[0]); return (-1); - } - #endif - - #if (!defined(vax) && !defined(tahoe) && !defined(pdp11)) || defined(VAX630) - scanc(size, cp, table, mask) - u_int size; - register u_char *cp, table[]; - register u_char mask; - { - register u_char *end = &cp[size]; - - while (cp < end && (table[*cp] & mask) == 0) - cp++; - return (end - cp); - } - #endif - - #if !defined(vax) && !defined(tahoe) && !defined(pdp11) - locc(mask, size, cp) - register u_char mask; - u_int size; - register u_char *cp; - { - register u_char *end = &cp[size]; - - while (cp < end && *cp != mask) - cp++; - return (end - cp); } #endif --- 170,174 ---- *** /usr/src/sys/sys/ufs_syscalls.c.old Sun Dec 24 15:30:35 1995 --- /usr/src/sys/sys/ufs_syscalls.c Mon Sep 16 21:10:02 1996 *************** *** 3,9 **** * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_syscalls.c 1.6 (2.11BSD GTE) 1995/12/24 */ #include "param.h" --- 3,9 ---- * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * ! * @(#)ufs_syscalls.c 1.7 (2.11BSD GTE) 1996/9/13 */ #include "param.h" *************** *** 198,204 **** } } if (mode & O_TRUNC) ! itrunc(ip, (u_long)0); iunlock(ip); fp->f_flag = mode&FMASK; fp->f_type = DTYPE_INODE; --- 198,204 ---- } } if (mode & O_TRUNC) ! itrunc(ip, (u_long)0, mode & O_FSYNC ? IO_SYNC : 0); iunlock(ip); fp->f_flag = mode&FMASK; fp->f_type = DTYPE_INODE; *************** *** 832,846 **** } /* - * Flush any pending I/O. - */ - sync() - { - - update(); - } - - /* * Truncate a file given its path name. */ truncate() --- 832,837 ---- *************** *** 1144,1150 **** if (doingdirectory) { if (--xp->i_nlink != 0) panic("rename: lnk dir"); ! itrunc(xp, (u_long)0); } xp->i_flag |= ICHG; iput(xp); --- 1135,1141 ---- if (doingdirectory) { if (--xp->i_nlink != 0) panic("rename: lnk dir"); ! itrunc(xp, (u_long)0, 0); /* IO_SYNC? */ } xp->i_flag |= ICHG; iput(xp); *************** *** 1494,1500 **** * worry about them later. */ ip->i_nlink -= 2; ! itrunc(ip, (u_long)0); cacheinval(ip); out: if (dp) --- 1485,1491 ---- * worry about them later. */ ip->i_nlink -= 2; ! itrunc(ip, (u_long)0, 0); /* IO_SYNC? */ cacheinval(ip); out: if (dp) *** /usr/src/sys/sys/ufs_syscalls2.c.old Sun Dec 31 12:12:18 1995 --- /usr/src/sys/sys/ufs_syscalls2.c Sat Sep 14 20:50:21 1996 *************** *** 1,5 **** /* ! * @(#) ufs_syscalls2.c 1.2 (2.11BSD) 1995/12/31 * * ufs_syscalls was getting too large. New UFS related system calls are * placed in this file. --- 1,5 ---- /* ! * @(#) ufs_syscalls2.c 1.3 (2.11BSD) 1996/9/13 * * ufs_syscalls was getting too large. New UFS related system calls are * placed in this file. *************** *** 9,17 **** --- 9,19 ---- #include "../machine/seg.h" #include "user.h" #include "inode.h" + #include "buf.h" #include "fs.h" #include "namei.h" #include "mount.h" + #include "kernel.h" statfs() { *************** *** 113,116 **** --- 115,193 ---- else u.u_r.r_val1 = count; return(0); + } + + /* + * 'ufs_sync' is the routine which syncs a single filesystem. This was + * created to replace 'update' which 'unmount' called. It seemed silly to + * sync _every_ filesystem when unmounting just one filesystem. + */ + + ufs_sync(mp) + register struct mount *mp; + { + register struct fs *fs; + struct buf *bp; + int error = 0; + + fs = &mp->m_filsys; + if (fs->fs_fmod && (mp->m_flags & MNT_RDONLY)) + { + printf("fs = %s\n", fs->fs_fsmnt); + panic("sync: rofs"); + } + syncinodes(fs); /* sync the inodes for this filesystem */ + bflush(mp->m_dev); /* flush dirty data blocks */ + #ifdef QUOTA + qsync(mp->m_dev); /* sync the quotas */ + #endif + + /* + * And lastly the superblock, if the filesystem was modified. + * Write back modified superblocks. Consistency check that the superblock + * of each file system is still in the buffer cache. + */ + if (fs->fs_fmod) + { + bp = getblk(mp->m_dev, SUPERB); + fs->fs_fmod = 0; + fs->fs_time = time.tv_sec; + bcopy(fs, mapin(bp), sizeof (struct fs)); + mapout(bp); + bwrite(bp); + error = geterror(bp); + } + return(error); + } + + /* + * This is somewhat inefficient in that the inode table is scanned for each + * filesystem but it didn't seem worth a page or two of code on something + * which only happens every 30 seconds. + */ + + syncinodes(fs) + struct fs *fs; + { + register struct inode *ip; + + /* + * Write back each (modified) inode. + */ + for (ip = inode; ip < inodeNINODE; ip++) + { + /* + * Attempt to reduce the overhead by short circuiting the scan if the + * inode is not for the filesystem being processed. + */ + if (ip->i_fs != fs) + continue; + if ((ip->i_flag & ILOCKED) != 0 || ip->i_count == 0 || + (ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0) + continue; + ip->i_flag |= ILOCKED; + ip->i_count++; + iupdat(ip, &time, &time, 0); + iput(ip); + } } *** /usr/src/sys/GENERIC/Makefile.old Mon Jun 17 20:04:04 1996 --- /usr/src/sys/GENERIC/Makefile Sat Sep 21 22:33:57 1996 *************** *** 10,16 **** # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # ! # 2.7 (2.11BSD GTE) 1996/6/8 # ######################################################### # Non-network, but separate I/D kernel # --- 10,16 ---- # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # ! # 2.7 (2.11BSD GTE) 1996/9/21 # ######################################################### # Non-network, but separate I/D kernel # *************** *** 52,58 **** subr_rmap.o subr_xxx.o sys_inode.o sys_pipe.o trap.o tty.o \ tty_conf.o tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o \ ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ ! ufs_subr.o xp.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= clock.o cons.o kern_time.o \ --- 52,58 ---- subr_rmap.o subr_xxx.o sys_inode.o sys_pipe.o trap.o tty.o \ tty_conf.o tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o \ ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ ! xp.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= clock.o cons.o kern_time.o \ *************** *** 64,70 **** OV6= tmscp.o tmscpdump.o OV7= rl.o mch_fpsim.o ingreslock.o ufs_disksubr.o OV8= rx.o kern_sysctl.o vm_sched.o vm_text.o ! OV9= kern_pdp.o kern_xxx.o ufs_syscalls2.o mem.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ --- 64,70 ---- OV6= tmscp.o tmscpdump.o OV7= rl.o mch_fpsim.o ingreslock.o ufs_disksubr.o OV8= rx.o kern_sysctl.o vm_sched.o vm_text.o ! OV9= kern_pdp.o kern_xxx.o ufs_syscalls2.o mem.o ufs_subr.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ *** /usr/src/sys/conf/Make.sunix.old Sun Jun 9 13:55:53 1996 --- /usr/src/sys/conf/Make.sunix Sat Sep 21 22:44:08 1996 *************** *** 9,15 **** # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # ! # 2.7 (2.11BSD GTE) 1996/6/8 # ######################################################### # Non-network, but separate I/D kernel # --- 9,15 ---- # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # ! # 2.7 (2.11BSD GTE) 1996/9/21 # ######################################################### # Non-network, but separate I/D kernel # *************** *** 51,57 **** subr_rmap.o subr_xxx.o sys_inode.o sys_pipe.o trap.o tty.o \ tty_conf.o tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o \ ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ ! ufs_subr.o xp.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= clock.o cons.o kern_time.o \ --- 51,57 ---- subr_rmap.o subr_xxx.o sys_inode.o sys_pipe.o trap.o tty.o \ tty_conf.o tty_subr.o tty_tb.o tty_tty.o ufs_alloc.o ufs_bio.o \ ufs_bmap.o ufs_dsort.o ufs_fio.o ufs_inode.o ufs_namei.o \ ! xp.o OV1= sys_generic.o ufs_syscalls.o OV2= kern_acct.o kern_exec.o kern_exit.o kern_fork.o kern_resource.o OV3= clock.o cons.o kern_time.o \ *************** *** 63,69 **** OV6= tmscp.o tmscpdump.o OV7= rl.o mch_fpsim.o ingreslock.o ufs_disksubr.o OV8= rx.o kern_sysctl.o vm_sched.o vm_text.o ! OV9= kern_pdp.o kern_xxx.o ufs_syscalls2.o mem.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ --- 63,69 ---- OV6= tmscp.o tmscpdump.o OV7= rl.o mch_fpsim.o ingreslock.o ufs_disksubr.o OV8= rx.o kern_sysctl.o vm_sched.o vm_text.o ! OV9= kern_pdp.o kern_xxx.o ufs_syscalls2.o mem.o ufs_subr.o KERNOBJ=${CONF} ${BASE} ${OV1} ${OV2} ${OV3} ${OV4} ${OV5} \ ${OV6} ${OV7} ${OV8} ${OV9} ${OV10} ${OV11} ${OV12} \ *** /VERSION.old Mon Sep 16 21:00:09 1996 --- /VERSION Sat Sep 21 21:29:06 1996 *************** *** 1,4 **** ! Current Patch Level: 330 2.11 BSD ============ --- 1,4 ---- ! Current Patch Level: 331 2.11 BSD ============