diff options
author | iedowse <iedowse@FreeBSD.org> | 2002-12-07 21:40:31 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2002-12-07 21:40:31 +0000 |
commit | f03bcbe2fa104e12f341376b76d3214b06425e38 (patch) | |
tree | 7d319207ab6d81b19df9aa32b336857325d796a7 /sbin | |
parent | 6da27e4c8e8646fdac92c74cab95a0db6816b98c (diff) | |
download | FreeBSD-src-f03bcbe2fa104e12f341376b76d3214b06425e38.zip FreeBSD-src-f03bcbe2fa104e12f341376b76d3214b06425e38.tar.gz |
Slow down the operation of background fsck so as to leave some disk
bandwidth for other processes. Since the sleeping is done from
userland, this avoids the locking issues that affected the kernel
version.
The algorithm used here is to measure a moving average of the times
taken by a sample of read operations and then delay 1 in 8 reads
by 16 times the measured average. This should correspond to a factor
of 3 slowdown, but in practice the factor is larger (3.5 to 4) due
to hz rounding effects.
Reviewed by: mckusick
Approved by: re
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/fsck_ffs/fsutil.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c index 0ce8663..c684b94 100644 --- a/sbin/fsck_ffs/fsutil.c +++ b/sbin/fsck_ffs/fsutil.c @@ -40,6 +40,7 @@ static const char rcsid[] = #endif /* not lint */ #include <sys/param.h> +#include <sys/time.h> #include <sys/types.h> #include <sys/sysctl.h> #include <sys/disklabel.h> @@ -62,7 +63,13 @@ static const char rcsid[] = #include "fsck.h" +static void slowio_start(void); +static void slowio_end(void); + long diskreads, totalreads; /* Disk cache statistics */ +struct timeval slowio_starttime; +int slowio_delay_usec = 10000; /* Initial IO delay for background fsck */ +int slowio_pollcnt; int ftypeok(union dinode *dp) @@ -350,10 +357,15 @@ bread(int fd, char *buf, ufs2_daddr_t blk, long size) offset = blk; offset *= dev_bsize; + if (bkgrdflag) + slowio_start(); if (lseek(fd, offset, 0) < 0) rwerror("SEEK BLK", blk); - else if (read(fd, buf, (int)size) == size) + else if (read(fd, buf, (int)size) == size) { + if (bkgrdflag) + slowio_end(); return (0); + } rwerror("READ BLK", blk); if (lseek(fd, offset, 0) < 0) rwerror("SEEK BLK", blk); @@ -465,6 +477,39 @@ freeblk(ufs2_daddr_t blkno, long frags) (void)pass4check(&idesc); } +/* Slow down IO so as to leave some disk bandwidth for other processes */ +void +slowio_start() +{ + + /* Delay one in every 8 operations by 16 times the average IO delay */ + slowio_pollcnt = (slowio_pollcnt + 1) & 7; + if (slowio_pollcnt == 0) { + usleep(slowio_delay_usec * 16); + gettimeofday(&slowio_starttime, NULL); + } +} + +void +slowio_end() +{ + struct timeval tv; + int delay_usec; + + if (slowio_pollcnt != 0) + return; + + /* Update the slowdown interval. */ + gettimeofday(&tv, NULL); + delay_usec = (tv.tv_sec - slowio_starttime.tv_sec) * 1000000 + + (tv.tv_usec - slowio_starttime.tv_usec); + if (delay_usec < 64) + delay_usec = 64; + if (delay_usec > 1000000) + delay_usec = 1000000; + slowio_delay_usec = (slowio_delay_usec * 63 + delay_usec) >> 6; +} + /* * Find a pathname */ |