summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>1999-04-29 18:15:25 +0000
committeralc <alc@FreeBSD.org>1999-04-29 18:15:25 +0000
commit9f01d1b1e7f08125c62ffe701ee4ee7e7b7faa14 (patch)
tree576f47d57d08a344bc1f467dd97b45182a5460a8 /sys/kern/vfs_bio.c
parent8a895b7c3427d09f8666f86280b3e4830ecd6ade (diff)
downloadFreeBSD-src-9f01d1b1e7f08125c62ffe701ee4ee7e7b7faa14.zip
FreeBSD-src-9f01d1b1e7f08125c62ffe701ee4ee7e7b7faa14.tar.gz
Address a performance problem in getnewbuf:
In heavy-writing situations, QUEUE_LRU can contain a large number of DELWRI buffers at its head. These buffers must be moved to the tail if they cannot be written async in order to reduce the scanning time required to skip past these buffers in later getnewbuf() calls. Submitted by: Matthew Dillon <dillon@apollo.backplane.com>
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 8a8d3a4..803aab1 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -11,7 +11,7 @@
* 2. Absolutely no warranty of function or purpose is made by the author
* John S. Dyson.
*
- * $Id: vfs_bio.c,v 1.205 1999/04/07 02:41:54 alc Exp $
+ * $Id: vfs_bio.c,v 1.206 1999/04/14 18:51:52 dt Exp $
*/
/*
@@ -1126,10 +1126,10 @@ getnewbuf(struct vnode *vp, daddr_t blkno,
{
struct buf *bp;
struct buf *nbp;
+ struct buf *dbp;
int outofspace;
int nqindex;
int defrag = 0;
- int countawrites = 0;
restart:
/*
@@ -1140,6 +1140,7 @@ restart:
* if both outofspace and defrag are on.
*/
+ dbp = NULL;
outofspace = 0;
if (bufspace >= hibufspace) {
if ((curproc->p_flag & P_FLSINPROG) == 0 ||
@@ -1264,16 +1265,43 @@ restart:
* to recover since it really isn't our job here.
*/
if ((bp->b_flags & (B_DELWRI | B_INVAL)) == B_DELWRI) {
+ /*
+ * This is rather complex, but necessary. If we come
+ * across a B_DELWRI buffer we have to flush it in
+ * order to use it. We only do this if we absolutely
+ * need to. We must also protect against too much
+ * recursion which might run us out of stack due to
+ * deep VFS call stacks.
+ *
+ * In heavy-writing situations, QUEUE_LRU can contain
+ * a large number of DELWRI buffers at its head. These
+ * buffers must be moved to the tail if they cannot be
+ * written async in order to reduce the scanning time
+ * required to skip past these buffers in later
+ * getnewbuf() calls.
+ */
if ((curproc->p_flag & P_FLSINPROG) ||
- numdirtybuffers < hidirtybuffers ||
- countawrites > 16
+ numdirtybuffers < hidirtybuffers
) {
+ if (qindex == QUEUE_LRU) {
+ /*
+ * dbp prevents us from looping forever
+ * if all bps in QUEUE_LRU are dirty.
+ */
+ if (bp == dbp) {
+ bp = NULL;
+ break;
+ }
+ if (dbp == NULL)
+ dbp = TAILQ_LAST(&bufqueues[QUEUE_LRU], bqueues);
+ TAILQ_REMOVE(&bufqueues[QUEUE_LRU], bp, b_freelist);
+ TAILQ_INSERT_TAIL(&bufqueues[QUEUE_LRU], bp, b_freelist);
+ }
continue;
}
curproc->p_flag |= P_FLSINPROG;
vfs_bio_awrite(bp);
curproc->p_flag &= ~P_FLSINPROG;
- ++countawrites;
goto restart;
}
OpenPOWER on IntegriCloud