summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2002-12-07 21:40:31 +0000
committeriedowse <iedowse@FreeBSD.org>2002-12-07 21:40:31 +0000
commitf03bcbe2fa104e12f341376b76d3214b06425e38 (patch)
tree7d319207ab6d81b19df9aa32b336857325d796a7 /sbin
parent6da27e4c8e8646fdac92c74cab95a0db6816b98c (diff)
downloadFreeBSD-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.c47
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
*/
OpenPOWER on IntegriCloud