NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/39052: assertion "!ISSET(bp->b_cflags, BC_BUSY)" failed



I added some checks, see the attached patch (the BC_PRIV flag is something
I added to check if private buffers from xbdback or vnd did show up
there). I got right at boot:

panic: kernel debugging assertion "!checkfreelist(bp, &bufqueues[BQ_LRU])" 
failed: file "/dsk/l1/misc/bouyer/current/src/sys/kern/vfs_bio.c", line 2093
fatal breakpoint trap in supervisor mode
trap type 1 code 0 rip ffffffff8050c345 cs 8 rflags 246 cr2  0 cpl 0 rsp 
ffffffff80dec7c0
Stopped in pid 0.1 (system) at  netbsd:breakpoint+0x5:  leave
db{1}> tr
breakpoint() at netbsd:breakpoint+0x5
panic() at netbsd:panic+0x260
__kernassert() at netbsd:__kernassert+0x2d
bbusy() at netbsd:bbusy+0x377
vinvalbuf() at netbsd:vinvalbuf+0x136
spec_close() at netbsd:spec_close+0x8c
VOP_CLOSE() at netbsd:VOP_CLOSE+0x62
cpu_rootconf() at netbsd:cpu_rootconf+0x7bc
main() at netbsd:main+0x24c

So it looks like we're marking BC_BUSY a buffer which is on the LRU queue.
Is it supposed to happen ? If so I guess we should check for it when looking
at recycling a buffer from the LRU queue, and maybe AGE too ?

-- 
Manuel Bouyer, LIP6, Universite Paris VI.           
Manuel.Bouyer%lip6.fr@localhost
     NetBSD: 26 ans d'experience feront toujours la difference
--
Index: vfs_bio.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_bio.c,v
retrieving revision 1.205
diff -u -r1.205 vfs_bio.c
--- vfs_bio.c   17 Jun 2008 19:14:14 -0000      1.205
+++ vfs_bio.c   27 Jun 2008 16:28:45 -0000
@@ -283,7 +283,7 @@
 }
 
 #ifdef DEBUG
-int debug_verify_freelist = 0;
+int debug_verify_freelist = 1;
 static int
 checkfreelist(buf_t *bp, struct bqueue *dp)
 {
@@ -309,6 +309,8 @@
 binsheadfree(buf_t *bp, struct bqueue *dp)
 {
 
+       KASSERT(mutex_owned(&bufcache_lock));
+       KASSERT(!ISSET(bp->b_cflags, BC_PRIV));
        KASSERT(bp->b_freelistindex == -1);
        TAILQ_INSERT_HEAD(&dp->bq_queue, bp, b_freelist);
        dp->bq_bytes += bp->b_bufsize;
@@ -319,6 +321,8 @@
 binstailfree(buf_t *bp, struct bqueue *dp)
 {
 
+       KASSERT(mutex_owned(&bufcache_lock));
+       KASSERT(!ISSET(bp->b_cflags, BC_PRIV));
        KASSERT(bp->b_freelistindex == -1);
        TAILQ_INSERT_TAIL(&dp->bq_queue, bp, b_freelist);
        dp->bq_bytes += bp->b_bufsize;
@@ -332,6 +336,7 @@
        int bqidx = bp->b_freelistindex;
 
        KASSERT(mutex_owned(&bufcache_lock));
+       KASSERT(!ISSET(bp->b_cflags, BC_PRIV));
 
        KASSERT(bqidx != -1);
        dp = &bufqueues[bqidx];
@@ -371,6 +376,10 @@
 
        KASSERT(mutex_owned(&bufcache_lock));
        KASSERT(bp->b_refcnt > 0);
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_AGE]));
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_LRU]));
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_LOCKED]));
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_EMPTY]));
 
        if (bp->b_refcnt-- == 1) {
                buf_destroy(bp);
@@ -972,6 +981,7 @@
        KASSERT(mutex_owned(&bufcache_lock));
        KASSERT(!cv_has_waiters(&bp->b_done));
        KASSERT(bp->b_refcnt > 0);
+       KASSERT(!ISSET(bp->b_cflags, BC_PRIV));
        
        SET(bp->b_cflags, set);
 
@@ -1014,9 +1024,9 @@
                }
        }
 
-       KDASSERT(checkfreelist(bp, &bufqueues[BQ_AGE]));
-       KDASSERT(checkfreelist(bp, &bufqueues[BQ_LRU]));
-       KDASSERT(checkfreelist(bp, &bufqueues[BQ_LOCKED]));
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_AGE]));
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_LRU]));
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_LOCKED]));
 
        if ((bp->b_bufsize <= 0) || ISSET(bp->b_cflags, BC_INVAL)) {
                /*
@@ -1286,7 +1296,7 @@
 buf_t *
 getnewbuf(int slpflag, int slptimeo, int from_bufq)
 {
-       buf_t *bp;
+       buf_t *bp, *abp, *lbp;
        struct vnode *vp;
 
  start:
@@ -1302,6 +1312,8 @@
                        memset((char *)bp, 0, sizeof(*bp));
                        buf_init(bp);
                        SET(bp->b_cflags, BC_BUSY);     /* mark buffer busy */
+                       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_AGE]));
+                       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_LRU]));
                        mutex_enter(&bufcache_lock);
 #if defined(DIAGNOSTIC)
                        bp->b_freelistindex = -1;
@@ -1310,10 +1322,16 @@
                }
                mutex_enter(&bufcache_lock);
        }
-
-       if ((bp = TAILQ_FIRST(&bufqueues[BQ_AGE].bq_queue)) != NULL ||
-           (bp = TAILQ_FIRST(&bufqueues[BQ_LRU].bq_queue)) != NULL) {
+       abp = lbp = NULL;
+       if ((bp = abp = TAILQ_FIRST(&bufqueues[BQ_AGE].bq_queue)) != NULL ||
+           (bp = lbp = TAILQ_FIRST(&bufqueues[BQ_LRU].bq_queue)) != NULL) {
+               if (bp->b_cflags & BC_BUSY) {
+                       printf("bp %p abp %p lbp %p b_cflags 0x%x "
+                           "b_flags 0x%x b_refcnt %d b_freelistindex %d b_vp 
%p b_oflags 0x%x\n", bp, abp, lbp, bp->b_cflags, bp->b_flags, bp->b_refcnt, 
bp->b_freelistindex, bp->b_vp, bp->b_oflags);
+                        panic("BC_BUSY");  
+               }
                KASSERT(!ISSET(bp->b_cflags, BC_BUSY));
+               KASSERT(!ISSET(bp->b_cflags, BC_PRIV));
                bremfree(bp);
 
                /* Buffer is no longer on free lists. */
@@ -1375,6 +1393,8 @@
                (*bioopsp->io_deallocate)(bp);
 
        /* clear out various other fields */
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_AGE]));
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_LRU]));
        bp->b_cflags = BC_BUSY;
        bp->b_oflags = 0;
        bp->b_flags = 0;
@@ -1603,6 +1623,8 @@
                            && (bp->b_vp->v_mount->mnt_flag & MNT_SOFTDEP)
                            && (bp->b_oflags & BO_DELWRI)) {
                                bremfree(bp);
+                               KDASSERT(!checkfreelist(bp, 
&bufqueues[BQ_AGE]));
+                               KDASSERT(!checkfreelist(bp, 
&bufqueues[BQ_LRU]));
                                bp->b_cflags |= BC_BUSY;
                                nbusy++;
                                mutex_exit(&bufcache_lock);
@@ -1964,7 +1986,10 @@
        const int b_read = mbp->b_flags & B_READ;
        struct vnode *vp = mbp->b_vp;
 
+       KASSERT(!ISSET(bp->b_cflags, BC_PRIV));
        KASSERT(mbp->b_bcount >= offset + size);
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_AGE]));
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_LRU]));
        bp->b_vp = vp;
        bp->b_objlock = mbp->b_objlock;
        bp->b_cflags = BC_BUSY;
@@ -2064,6 +2089,8 @@
                        return error;
                return EPASSTHROUGH;
        }
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_AGE]));
+       KDASSERT(!checkfreelist(bp, &bufqueues[BQ_LRU]));
        bp->b_cflags |= BC_BUSY;
 
        return 0;


Home | Main Index | Thread Index | Old Index