tech-kern 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