kern/39052: fix broken assertion. We can have a BC_BUSY buffer in the LRU

queue, if it's being flushed. But in this case, we'll also have B_VFLUSH.

While there fix checkfreelist() so that it can be used to check that a
buffer is not in the free lists.
This commit is contained in:
bouyer 2008-07-06 15:00:45 +00:00
parent 163f9db0b9
commit 52346627a5
1 changed files with 14 additions and 12 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_bio.c,v 1.205 2008/06/17 19:14:14 mlelstv Exp $ */ /* $NetBSD: vfs_bio.c,v 1.206 2008/07/06 15:00:45 bouyer Exp $ */
/*- /*-
* Copyright (c) 2007, 2008 The NetBSD Foundation, Inc. * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
@ -107,7 +107,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.205 2008/06/17 19:14:14 mlelstv Exp $"); __KERNEL_RCSID(0, "$NetBSD: vfs_bio.c,v 1.206 2008/07/06 15:00:45 bouyer Exp $");
#include "fs_ffs.h" #include "fs_ffs.h"
#include "opt_bufcache.h" #include "opt_bufcache.h"
@ -167,7 +167,7 @@ static void binsheadfree(buf_t *, struct bqueue *);
static void binstailfree(buf_t *, struct bqueue *); static void binstailfree(buf_t *, struct bqueue *);
int count_lock_queue(void); /* XXX */ int count_lock_queue(void); /* XXX */
#ifdef DEBUG #ifdef DEBUG
static int checkfreelist(buf_t *, struct bqueue *); static int checkfreelist(buf_t *, struct bqueue *, int);
#endif #endif
static void biointr(void *); static void biointr(void *);
static void biodone2(buf_t *); static void biodone2(buf_t *);
@ -285,7 +285,7 @@ buf_setwm(void)
#ifdef DEBUG #ifdef DEBUG
int debug_verify_freelist = 0; int debug_verify_freelist = 0;
static int static int
checkfreelist(buf_t *bp, struct bqueue *dp) checkfreelist(buf_t *bp, struct bqueue *dp, int ison)
{ {
buf_t *b; buf_t *b;
@ -294,10 +294,10 @@ checkfreelist(buf_t *bp, struct bqueue *dp)
TAILQ_FOREACH(b, &dp->bq_queue, b_freelist) { TAILQ_FOREACH(b, &dp->bq_queue, b_freelist) {
if (b == bp) if (b == bp)
return 1; return ison ? 1 : 0;
} }
return 0; return ison ? 0 : 1;
} }
#endif #endif
@ -309,6 +309,7 @@ static void
binsheadfree(buf_t *bp, struct bqueue *dp) binsheadfree(buf_t *bp, struct bqueue *dp)
{ {
KASSERT(mutex_owned(&bufcache_lock));
KASSERT(bp->b_freelistindex == -1); KASSERT(bp->b_freelistindex == -1);
TAILQ_INSERT_HEAD(&dp->bq_queue, bp, b_freelist); TAILQ_INSERT_HEAD(&dp->bq_queue, bp, b_freelist);
dp->bq_bytes += bp->b_bufsize; dp->bq_bytes += bp->b_bufsize;
@ -319,6 +320,7 @@ static void
binstailfree(buf_t *bp, struct bqueue *dp) binstailfree(buf_t *bp, struct bqueue *dp)
{ {
KASSERT(mutex_owned(&bufcache_lock));
KASSERT(bp->b_freelistindex == -1); KASSERT(bp->b_freelistindex == -1);
TAILQ_INSERT_TAIL(&dp->bq_queue, bp, b_freelist); TAILQ_INSERT_TAIL(&dp->bq_queue, bp, b_freelist);
dp->bq_bytes += bp->b_bufsize; dp->bq_bytes += bp->b_bufsize;
@ -335,7 +337,7 @@ bremfree(buf_t *bp)
KASSERT(bqidx != -1); KASSERT(bqidx != -1);
dp = &bufqueues[bqidx]; dp = &bufqueues[bqidx];
KDASSERT(checkfreelist(bp, dp)); KDASSERT(checkfreelist(bp, dp, 1));
KASSERT(dp->bq_bytes >= bp->b_bufsize); KASSERT(dp->bq_bytes >= bp->b_bufsize);
TAILQ_REMOVE(&dp->bq_queue, bp, b_freelist); TAILQ_REMOVE(&dp->bq_queue, bp, b_freelist);
dp->bq_bytes -= bp->b_bufsize; dp->bq_bytes -= bp->b_bufsize;
@ -1007,16 +1009,16 @@ brelsel(buf_t *bp, int set)
CLR(bp->b_cflags, BC_VFLUSH); CLR(bp->b_cflags, BC_VFLUSH);
if (!ISSET(bp->b_cflags, BC_INVAL|BC_AGE) && if (!ISSET(bp->b_cflags, BC_INVAL|BC_AGE) &&
!ISSET(bp->b_flags, B_LOCKED) && bp->b_error == 0) { !ISSET(bp->b_flags, B_LOCKED) && bp->b_error == 0) {
KDASSERT(checkfreelist(bp, &bufqueues[BQ_LRU])); KDASSERT(checkfreelist(bp, &bufqueues[BQ_LRU], 1));
goto already_queued; goto already_queued;
} else { } else {
bremfree(bp); bremfree(bp);
} }
} }
KDASSERT(checkfreelist(bp, &bufqueues[BQ_AGE])); KDASSERT(checkfreelist(bp, &bufqueues[BQ_AGE], 0));
KDASSERT(checkfreelist(bp, &bufqueues[BQ_LRU])); KDASSERT(checkfreelist(bp, &bufqueues[BQ_LRU], 0));
KDASSERT(checkfreelist(bp, &bufqueues[BQ_LOCKED])); KDASSERT(checkfreelist(bp, &bufqueues[BQ_LOCKED], 0));
if ((bp->b_bufsize <= 0) || ISSET(bp->b_cflags, BC_INVAL)) { if ((bp->b_bufsize <= 0) || ISSET(bp->b_cflags, BC_INVAL)) {
/* /*
@ -1313,7 +1315,7 @@ getnewbuf(int slpflag, int slptimeo, int from_bufq)
if ((bp = TAILQ_FIRST(&bufqueues[BQ_AGE].bq_queue)) != NULL || if ((bp = TAILQ_FIRST(&bufqueues[BQ_AGE].bq_queue)) != NULL ||
(bp = TAILQ_FIRST(&bufqueues[BQ_LRU].bq_queue)) != NULL) { (bp = TAILQ_FIRST(&bufqueues[BQ_LRU].bq_queue)) != NULL) {
KASSERT(!ISSET(bp->b_cflags, BC_BUSY)); KASSERT(!ISSET(bp->b_cflags, BC_BUSY) || ISSET(bp->b_cflags, BC_VFLUSH));
bremfree(bp); bremfree(bp);
/* Buffer is no longer on free lists. */ /* Buffer is no longer on free lists. */