Keep track of the number of buffers undgoing IO, and include that number
authorMatthew Dillon <dillon@dragonflybsd.org>
Tue, 6 May 2008 00:14:12 +0000 (00:14 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Tue, 6 May 2008 00:14:12 +0000 (00:14 +0000)
in calculations involving numdirtybuffers.  This prevents the kernel from
believing that there are only a few dirty buffers when, in fact, all the
dirty buffers are running IOs.

sys/kern/vfs_bio.c
sys/kern/vfs_cluster.c
sys/sys/buf.h
sys/vfs/specfs/spec_vnops.c

index 969418a..42fb7d3 100644 (file)
@@ -12,7 +12,7 @@
  *             John S. Dyson.
  *
  * $FreeBSD: src/sys/kern/vfs_bio.c,v 1.242.2.20 2003/05/28 18:38:10 alc Exp $
- * $DragonFly: src/sys/kern/vfs_bio.c,v 1.100 2008/04/30 04:11:44 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_bio.c,v 1.101 2008/05/06 00:13:53 dillon Exp $
  */
 
 /*
@@ -108,7 +108,6 @@ static void buf_daemon_hw(void);
  * but the code is intricate enough already.
  */
 vm_page_t bogus_page;
-int runningbufspace;
 
 /*
  * These are all static, but make the ones we export globals so we do
@@ -119,6 +118,7 @@ int bufspace, maxbufspace,
 static int bufreusecnt, bufdefragcnt, buffreekvacnt;
 static int lorunningspace, hirunningspace, runningbufreq;
 int numdirtybuffers, numdirtybuffershw, lodirtybuffers, hidirtybuffers;
+int runningbufspace, runningbufcount;
 static int numfreebuffers, lofreebuffers, hifreebuffers;
 static int getnewbufcalls;
 static int getnewbufrestarts;
@@ -154,6 +154,8 @@ SYSCTL_INT(_vfs, OID_AUTO, numfreebuffers, CTLFLAG_RD, &numfreebuffers, 0,
        "Number of free buffers on the buffer cache free list");
 SYSCTL_INT(_vfs, OID_AUTO, runningbufspace, CTLFLAG_RD, &runningbufspace, 0,
        "I/O bytes currently in progress due to asynchronous writes");
+SYSCTL_INT(_vfs, OID_AUTO, runningbufcount, CTLFLAG_RD, &runningbufcount, 0,
+       "I/O buffers currently in progress due to asynchronous writes");
 SYSCTL_INT(_vfs, OID_AUTO, maxbufspace, CTLFLAG_RD, &maxbufspace, 0,
        "Hard limit on maximum amount of memory usable for buffer space");
 SYSCTL_INT(_vfs, OID_AUTO, hibufspace, CTLFLAG_RD, &hibufspace, 0,
@@ -197,7 +199,8 @@ extern int vm_swap_size;
 static __inline void
 numdirtywakeup(void)
 {
-       if (numdirtybuffers <= (lodirtybuffers + hidirtybuffers) / 2) {
+       if (runningbufcount + numdirtybuffers <= 
+           (lodirtybuffers + hidirtybuffers) / 2) {
                if (needsbuffer & VFS_BIO_NEED_DIRTYFLUSH) {
                        spin_lock_wr(&needsbuffer_spin);
                        needsbuffer &= ~VFS_BIO_NEED_DIRTYFLUSH;
@@ -243,11 +246,13 @@ runningbufwakeup(struct buf *bp)
 {
        if (bp->b_runningbufspace) {
                runningbufspace -= bp->b_runningbufspace;
+               --runningbufcount;
                bp->b_runningbufspace = 0;
                if (runningbufreq && runningbufspace <= lorunningspace) {
                        runningbufreq = 0;
                        wakeup(&runningbufreq);
                }
+               numdirtywakeup();
        }
 }
 
@@ -339,13 +344,15 @@ static __inline__
 void
 bd_wakeup(int dirtybuflevel)
 {
-       if (bd_request == 0 && numdirtybuffers >= dirtybuflevel) {
+       if (bd_request == 0 && numdirtybuffers && 
+           runningbufcount + numdirtybuffers >= dirtybuflevel) {
                spin_lock_wr(&needsbuffer_spin);
                bd_request = 1;
                spin_unlock_wr(&needsbuffer_spin);
                wakeup(&bd_request);
        }
-       if (bd_request_hw == 0 && numdirtybuffershw >= dirtybuflevel) {
+       if (bd_request_hw == 0 && numdirtybuffershw &&
+           numdirtybuffershw >= dirtybuflevel) {
                spin_lock_wr(&needsbuffer_spin);
                bd_request_hw = 1;
                spin_unlock_wr(&needsbuffer_spin);
@@ -742,7 +749,10 @@ bwrite(struct buf *bp)
         * valid for vnode-backed buffers.
         */
        bp->b_runningbufspace = bp->b_bufsize;
-       runningbufspace += bp->b_runningbufspace;
+       if (bp->b_runningbufspace) {
+               runningbufspace += bp->b_runningbufspace;
+               ++runningbufcount;
+       }
 
        crit_exit();
        if (oldflags & B_ASYNC)
@@ -956,12 +966,13 @@ bowrite(struct buf *bp)
 void
 bwillwrite(void)
 {
-       if (numdirtybuffers >= hidirtybuffers / 2) {
+       if (runningbufcount + numdirtybuffers >= hidirtybuffers / 2) {
                bd_wakeup(1);
-               while (numdirtybuffers >= hidirtybuffers) {
+               while (runningbufcount + numdirtybuffers >= hidirtybuffers) {
                        bd_wakeup(1);
                        spin_lock_wr(&needsbuffer_spin);
-                       if (numdirtybuffers >= hidirtybuffers) {
+                       if (runningbufcount + numdirtybuffers >= 
+                           hidirtybuffers) {
                                needsbuffer |= VFS_BIO_NEED_DIRTYFLUSH;
                                msleep(&needsbuffer, &needsbuffer_spin, 0,
                                       "flswai", 0);
@@ -971,10 +982,10 @@ bwillwrite(void)
        } 
 #if 0
        /* FUTURE - maybe */
-       else if (numdirtybuffershw > hidirtybuffers / 2) {
+       else if (runningbufcount + numdirtybuffershw > hidirtybuffers / 2) {
                bd_wakeup(1);
 
-               while (numdirtybuffershw > hidirtybuffers) {
+               while (runningbufcount + numdirtybuffershw > hidirtybuffers) {
                        needsbuffer |= VFS_BIO_NEED_DIRTYFLUSH;
                        tsleep(&needsbuffer, slpflags, "newbuf",
                               slptimeo);
@@ -991,7 +1002,7 @@ bwillwrite(void)
 int
 buf_dirty_count_severe(void)
 {
-       return(numdirtybuffers >= hidirtybuffers);
+       return(runningbufcount + numdirtybuffers >= hidirtybuffers);
 }
 
 /*
@@ -1981,6 +1992,9 @@ buf_daemon(void)
                        waitrunningbufspace();
                        numdirtywakeup();
                }
+               if (runningbufcount + numdirtybuffers > lodirtybuffers) {
+                       waitrunningbufspace();
+               }
                numdirtywakeup();
 
                /*
@@ -1993,7 +2007,7 @@ buf_daemon(void)
                 * find any flushable buffers, we sleep half a second. 
                 * Otherwise we loop immediately.
                 */
-               if (numdirtybuffers <= lodirtybuffers) {
+               if (runningbufcount + numdirtybuffers <= lodirtybuffers) {
                        /*
                         * We reached our low water mark, reset the
                         * request and sleep until we are needed again.
@@ -2044,6 +2058,9 @@ buf_daemon_hw(void)
                        waitrunningbufspace();
                        numdirtywakeup();
                }
+               if (runningbufcount + numdirtybuffershw > lodirtybuffers) {
+                       waitrunningbufspace();
+               }
 
                /*
                 * Only clear bd_request if we have reached our low water
@@ -2055,7 +2072,7 @@ buf_daemon_hw(void)
                 * find any flushable buffers, we sleep half a second. 
                 * Otherwise we loop immediately.
                 */
-               if (numdirtybuffershw <= lodirtybuffers) {
+               if (runningbufcount + numdirtybuffershw <= lodirtybuffers) {
                        /*
                         * We reached our low water mark, reset the
                         * request and sleep until we are needed again.
index c49efbf..37a0914 100644 (file)
@@ -34,7 +34,7 @@
  *
  *     @(#)vfs_cluster.c       8.7 (Berkeley) 2/13/94
  * $FreeBSD: src/sys/kern/vfs_cluster.c,v 1.92.2.9 2001/11/18 07:10:59 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_cluster.c,v 1.33 2008/04/22 18:46:51 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_cluster.c,v 1.34 2008/05/06 00:13:54 dillon Exp $
  */
 
 #include "opt_debug_cluster.h"
@@ -937,7 +937,10 @@ cluster_wbuild(struct vnode *vp, int size, off_t start_loffset, int bytes)
                bp->b_cmd = BUF_CMD_WRITE;
                vfs_busy_pages(vp, bp);
                bp->b_runningbufspace = bp->b_bufsize;
-               runningbufspace += bp->b_runningbufspace;
+               if (bp->b_runningbufspace) {
+                       runningbufspace += bp->b_runningbufspace;
+                       ++runningbufcount;
+               }
                BUF_KERNPROC(bp);       /* B_ASYNC */
                vn_strategy(vp, &bp->b_bio1);
 
index 8504b31..4660c40 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)buf.h       8.9 (Berkeley) 3/30/95
  * $FreeBSD: src/sys/sys/buf.h,v 1.88.2.10 2003/01/25 19:02:23 dillon Exp $
- * $DragonFly: src/sys/sys/buf.h,v 1.44 2008/04/22 18:46:52 dillon Exp $
+ * $DragonFly: src/sys/sys/buf.h,v 1.45 2008/05/06 00:14:11 dillon Exp $
  */
 
 #ifndef _SYS_BUF_H_
@@ -285,7 +285,7 @@ struct buf {
        "\40unused31\37cluster\36vmio\35ram\34ordered" \
        "\33paging\32vndirty\31vnclean\30want\27relbuf\26dirty" \
        "\25unused20\24raw\23unused18\22clusterok\21malloc\20nocache" \
-       "\17locked\16inval\15unused12\14error\13eintr\12unused9\11unused8" \
+       "\17locked\16inval\15unused12\14error\13eintr\12unused9\11bnoclip" \
        "\10delwri\7hashed\6cache\5deferred\4direct\3async\2needcommit\1age"
 
 #define        NOOFFSET        (-1LL)          /* No buffer offset calculated yet */
@@ -339,6 +339,7 @@ extern int  nbuf;                   /* The number of buffer headers */
 extern int     maxswzone;              /* Max KVA for swap structures */
 extern int     maxbcache;              /* Max KVA for buffer cache */
 extern int     runningbufspace;
+extern int     runningbufcount;
 extern int      buf_maxio;              /* nominal maximum I/O for buffer */
 extern struct buf *buf;                        /* The buffer headers. */
 extern char    *buffers;               /* The buffer contents. */
index 26f0fbc..5971017 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)spec_vnops.c        8.14 (Berkeley) 5/21/95
  * $FreeBSD: src/sys/miscfs/specfs/spec_vnops.c,v 1.131.2.4 2001/02/26 04:23:20 jlemon Exp $
- * $DragonFly: src/sys/vfs/specfs/spec_vnops.c,v 1.57 2007/11/06 03:50:02 dillon Exp $
+ * $DragonFly: src/sys/vfs/specfs/spec_vnops.c,v 1.58 2008/05/06 00:14:12 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -854,7 +854,10 @@ spec_getpages(struct vop_getpages_args *ap)
        bp->b_bcount = size;
        bp->b_resid = 0;
        bp->b_runningbufspace = size;
-       runningbufspace += bp->b_runningbufspace;
+       if (size) {
+               runningbufspace += bp->b_runningbufspace;
+               ++runningbufcount;
+       }
 
        bp->b_bio1.bio_offset = offset;
        bp->b_bio1.bio_done = spec_getpages_iodone;