summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1999-12-20 20:28:40 +0000
committerdillon <dillon@FreeBSD.org>1999-12-20 20:28:40 +0000
commit885c27b720bff004eb536dcaab0c32778e82457e (patch)
tree0e51fefc922990dce2952098cbb5723e1d38f8cf /sys/kern/vfs_bio.c
parentaac552da070206cb4ea1c87a066e8c632bcf774e (diff)
downloadFreeBSD-src-885c27b720bff004eb536dcaab0c32778e82457e.zip
FreeBSD-src-885c27b720bff004eb536dcaab0c32778e82457e.tar.gz
Reimplement buf_daemon / getnewbuf() interaction for dealing with
stressful situations. buf_daemon now makes a distinction between being woken up and its sleep timing out, and as a consequence is now much better able to dynamically tune itself to its environment. Reviewed by: Alfred Perlstein <bright@wintelcom.net>
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c89
1 files changed, 43 insertions, 46 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index dd135cf..c24a4e0 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -88,7 +88,7 @@ static int bufspace, maxbufspace, vmiospace,
bufmallocspace, maxbufmallocspace, hibufspace;
static int maxbdrun;
static int needsbuffer;
-static int numdirtybuffers, lodirtybuffers, hidirtybuffers;
+static int numdirtybuffers, hidirtybuffers;
static int numfreebuffers, lofreebuffers, hifreebuffers;
static int getnewbufcalls;
static int getnewbufrestarts;
@@ -96,8 +96,6 @@ static int kvafreespace;
SYSCTL_INT(_vfs, OID_AUTO, numdirtybuffers, CTLFLAG_RD,
&numdirtybuffers, 0, "");
-SYSCTL_INT(_vfs, OID_AUTO, lodirtybuffers, CTLFLAG_RW,
- &lodirtybuffers, 0, "");
SYSCTL_INT(_vfs, OID_AUTO, hidirtybuffers, CTLFLAG_RW,
&hidirtybuffers, 0, "");
SYSCTL_INT(_vfs, OID_AUTO, numfreebuffers, CTLFLAG_RD,
@@ -275,6 +273,16 @@ bd_wakeup(int dirtybuflevel)
}
}
+/*
+ * bd_speedup - speedup the buffer cache flushing code
+ */
+
+static __inline__
+void
+bd_speedup(void)
+{
+ bd_wakeup(1);
+}
/*
* Initialize buffer headers and related structures.
@@ -353,7 +361,6 @@ bufinit(void)
* Reduce the chance of a deadlock occuring by limiting the number
* of delayed-write dirty buffers we allow to stack up.
*/
- lodirtybuffers = nbuf / 7 + 10;
hidirtybuffers = nbuf / 4 + 20;
numdirtybuffers = 0;
/*
@@ -365,14 +372,9 @@ bufinit(void)
* the buffer cache.
*/
while (hidirtybuffers * BKVASIZE > 3 * hibufspace / 4) {
- lodirtybuffers >>= 1;
hidirtybuffers >>= 1;
buf_maxio >>= 1;
}
- if (lodirtybuffers < 2) {
- lodirtybuffers = 2;
- hidirtybuffers = 4;
- }
/*
* Temporary, BKVASIZE may be manipulated soon, make sure we don't
@@ -799,9 +801,9 @@ bowrite(struct buf * bp)
void
bwillwrite(void)
{
- int twenty = (hidirtybuffers - lodirtybuffers) / 5;
+ int slop = hidirtybuffers / 10;
- if (numdirtybuffers > hidirtybuffers + twenty) {
+ if (numdirtybuffers > hidirtybuffers + slop) {
int s;
s = splbio();
@@ -1571,9 +1573,8 @@ restart:
flags = VFS_BIO_NEED_ANY;
}
- /* XXX */
+ bd_speedup(); /* heeeelp */
- (void) speedup_syncer();
needsbuffer |= flags;
while (needsbuffer & flags) {
if (tsleep(&needsbuffer, (PRIBIO + 4) | slpflag,
@@ -1652,6 +1653,7 @@ waitfreebuffers(int slpflag, int slptimeo)
static struct proc *bufdaemonproc;
static int bd_interval;
static int bd_flushto;
+static int bd_flushinc;
static struct kproc_desc buf_kp = {
"bufdaemon",
@@ -1672,6 +1674,7 @@ buf_daemon()
bd_interval = 5 * hz; /* dynamically adjusted */
bd_flushto = hidirtybuffers; /* dynamically adjusted */
+ bd_flushinc = 1;
while (TRUE) {
bd_request = 0;
@@ -1694,44 +1697,38 @@ buf_daemon()
}
}
- /*
- * If nobody is requesting anything we sleep
- */
- if (bd_request == 0)
- tsleep(&bd_request, PVM, "psleep", bd_interval);
+ if (bd_request ||
+ tsleep(&bd_request, PVM, "psleep", bd_interval) == 0) {
+ /*
+ * Another request is pending or we were woken up
+ * without timing out. Flush more.
+ */
+ --bd_flushto;
+ if (bd_flushto >= numdirtybuffers - 5) {
+ bd_flushto = numdirtybuffers - 10;
+ bd_flushinc = 1;
+ }
+ if (bd_flushto < 2)
+ bd_flushto = 2;
+ } else {
+ /*
+ * We slept and timed out, we can slow down.
+ */
+ bd_flushto += bd_flushinc;
+ if (bd_flushto > hidirtybuffers)
+ bd_flushto = hidirtybuffers;
+ ++bd_flushinc;
+ if (bd_flushinc > hidirtybuffers / 20 + 1)
+ bd_flushinc = hidirtybuffers / 20 + 1;
+ }
/*
- * We calculate how much to add or subtract from bd_flushto
- * and bd_interval based on how far off we are from the
- * optimal number of dirty buffers, which is 20% below the
- * hidirtybuffers mark. We cannot use hidirtybuffers straight
- * because being right on the mark will cause getnewbuf()
- * to oscillate our wakeup.
- *
- * The larger the error in either direction, the more we adjust
- * bd_flushto and bd_interval. The time interval is adjusted
- * by 2 seconds per whole-buffer-range of error. This is an
- * exponential convergence algorithm, with large errors
- * producing large changes and small errors producing small
- * changes.
+ * Set the interval on a linear scale based on hidirtybuffers
+ * with a maximum frequency of 1/10 second.
*/
-
- {
- int brange = hidirtybuffers - lodirtybuffers;
- int middb = hidirtybuffers - brange / 5;
- int deltabuf = middb - numdirtybuffers;
-
- bd_flushto += deltabuf / 20;
- bd_interval += deltabuf * (2 * hz) / (brange * 1);
- }
- if (bd_flushto < lodirtybuffers)
- bd_flushto = lodirtybuffers;
- if (bd_flushto > hidirtybuffers)
- bd_flushto = hidirtybuffers;
+ bd_interval = bd_flushto * 5 * hz / hidirtybuffers;
if (bd_interval < hz / 10)
bd_interval = hz / 10;
- if (bd_interval > 5 * hz)
- bd_interval = 5 * hz;
}
}
OpenPOWER on IntegriCloud