From f03bcbe2fa104e12f341376b76d3214b06425e38 Mon Sep 17 00:00:00 2001 From: iedowse Date: Sat, 7 Dec 2002 21:40:31 +0000 Subject: 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 --- sbin/fsck_ffs/fsutil.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'sbin') 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 +#include #include #include #include @@ -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 */ -- cgit v1.1