Return to BSD News archive
Newsgroups: comp.bugs.2bsd
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!nntp.coast.net!howland.erols.net!cs.utexas.edu!news.sprintlink.net!news-peer.sprintlink.net!news.mathworks.com!uunet!in3.uu.net!news.new-york.net!wlbr!moe.2bsd.com!sms
From: sms@moe.2bsd.com (Steven M. Schultz)
Subject: 'mount -o async' kernel support (finally) implemented (#331)
Organization: 2BSD, Simi Valley CA USA
Message-ID: <DyKxIp.LLB@moe.2bsd.com>
Date: Tue, 1 Oct 1996 04:23:13 GMT
Lines: 1847
NOTE: Apply #332 before recompiling the kernel. A bug was fixed
after this kit had already been created.
Subject: 'mount -o async' kernel support (finally) implemented (#331)
Index: sys/sys/<many> 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
============