summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2001-03-30 10:30:27 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2001-03-30 10:30:27 +0000
commit74785f8c870c0b7d87671a677d71a072c8a246b5 (patch)
tree5980689bb5e31a65ac0106a59bbab6e773740440 /sys/kern/vfs_bio.c
parentc89431ac8868973d20fef0bc9c1314fc59b3e260 (diff)
Avoid a 'thundering herd' problem when many processes wait for free buffers.
Just wakeup one process (there is a possible bug here that will be fixed in the next round of cleanup). Some misc cleanup, especially in the comments.
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index b2eef4e5ac5..5ba80311513 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_bio.c,v 1.35 2001/03/14 14:41:04 art Exp $ */
+/* $OpenBSD: vfs_bio.c,v 1.36 2001/03/30 10:30:26 art Exp $ */
/* $NetBSD: vfs_bio.c,v 1.44 1996/06/11 11:15:36 pk Exp $ */
/*-
@@ -108,7 +108,18 @@ static __inline struct buf *bio_doread __P((struct vnode *, daddr_t, int,
struct ucred *, int));
int count_lock_queue __P((void));
-/* We are currently only using *cleanbufs, but count all num*bufs */
+/*
+ * We keep a few counters to monitor the utilization of the buffer cache
+ *
+ * numdirtybufs - number of dirty (B_DELWRI) buffers. unused.
+ * lodirtybufs - ? unused.
+ * hidirtybufs - ? unused.
+ * numfreebufs - number of buffers on BQ_LRU and BQ_AGE. unused.
+ * numcleanbufs - number of clean (!B_DELWRI) buffers on BQ_LRU and BQ_AGE.
+ * Used to track the need to speedup the syncer and for the syncer reserve.
+ * numemptybufs - number of buffers on BQ_EMPTY. unused.
+ * mincleanbufs - the lowest number of clean buffers this far.
+ */
int numdirtybufs; /* number of all dirty buffers */
int lodirtybufs, hidirtybufs;
int numfreebufs; /* number of buffers on LRU+AGE free lists */
@@ -602,18 +613,16 @@ already_queued:
/* Allow disk interrupts. */
splx(s);
- /* Wake up syncer process waiting for any buffer to become free. */
+ /* Wake up syncer process waiting for buffers */
if (syncer_needbuffer) {
+ wakeup(&syncer_needbuffer);
syncer_needbuffer = 0;
- wakeup_one(&syncer_needbuffer);
}
- if (numcleanbufs < locleanbufs + min(locleanbufs, 4))
- speedup_syncer();
/* Wake up any processes waiting for any buffer to become free. */
if (needbuffer && (numcleanbufs > locleanbufs)) {
- needbuffer = 0;
- wakeup(&needbuffer);
+ needbuffer--;
+ wakeup_one(&needbuffer);
}
/* Wake up any proceeses waiting for _this_ buffer to become free. */
@@ -714,6 +723,7 @@ start:
splx(s);
}
allocbuf(bp, size);
+
return (bp);
}
@@ -839,11 +849,15 @@ getnewbuf(slpflag, slptimeo)
start:
s = splbio();
+ /*
+ * If we're getting low on buffers kick the syncer to work harder.
+ */
+ if (numcleanbufs < locleanbufs + min(locleanbufs, 4))
+ speedup_syncer();
+
if ((numcleanbufs <= locleanbufs) && curproc != syncerproc) {
/* wait for a free buffer of any kind */
- if (needbuffer == 0)
- speedup_syncer();
- needbuffer = 1;
+ needbuffer++;
tsleep(&needbuffer, slpflag|(PRIBIO+1), "getnewbuf", slptimeo);
splx(s);
return (0);