diff options
-rw-r--r-- | sys/kern/vfs_bio.c | 38 |
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; } |