FreeBSD/sys/kern/vfs_bio.c
/*
 *	buf_qrecycle:
 *
 *	Free a buffer from the given bufqueue.  kva controls whether the
 *	freed buf must own some kva resources.  This is used for
 *	defragmenting.
 */
Free a buffer from the given bufqueue.  kva controls whether the
freed buf must own some kva resources.  This is used for
defragmenting.
Free a buffer from the given bufqueue . kva controls whether the freed buf must own some kva resources . This is used for defragmenting .
static int
buf_qrecycle(int qindex, bool kva)
{
	struct buf *bp, *nbp;
	if (kva)
		atomic_add_int(&bufdefragcnt, 1);
	nbp = NULL;
	mtx_lock(&bqlocks[qindex]);
	nbp = TAILQ_FIRST(&bufqueues[qindex]);
	while ((bp = nbp) != NULL) {
		nbp = TAILQ_NEXT(bp, b_freelist);
		if (kva && bp->b_kvasize == 0)
			continue;
		if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL) != 0)
			continue;
		if ((bp->b_vflags & BV_BKGRDINPROG) != 0) {
			BUF_UNLOCK(bp);
			continue;
		}
		KASSERT(bp->b_qindex == qindex,
		    ("getnewbuf: inconsistent queue %d bp %p", qindex, bp));
		bremfreel(bp);
		mtx_unlock(&bqlocks[qindex]);
		if ((bp->b_vflags & BV_BKGRDERR) != 0) {
			bqrelse(bp);
			mtx_lock(&bqlocks[qindex]);
			nbp = TAILQ_FIRST(&bufqueues[qindex]);
			continue;
		}
		bp->b_flags |= B_INVAL;
		brelse(bp);
		return (0);
	}
	mtx_unlock(&bqlocks[qindex]);
	return (ENOBUFS);
}
static int buf_qrecycle ( int qindex , bool kva ) { struct buf * bp , * nbp ; if ( kva ) atomic_add_int ( & bufdefragcnt , 1 ) ; nbp = NULL ; mtx_lock ( & bqlocks [ qindex ] ) ; nbp = TAILQ_FIRST ( & bufqueues [ qindex ] ) ; while ( ( bp = nbp ) != NULL ) { nbp = TAILQ_NEXT ( bp , b_freelist ) ; if ( kva && bp -> b_kvasize == 0 ) continue ; if ( BUF_LOCK ( bp , LK_EXCLUSIVE | LK_NOWAIT , NULL ) != 0 ) continue ; if ( ( bp -> b_vflags & BV_BKGRDINPROG ) != 0 ) { BUF_UNLOCK ( bp ) ; continue ; } KASSERT ( bp -> b_qindex == qindex , ( " " , qindex , bp ) ) ; bremfreel ( bp ) ; mtx_unlock ( & bqlocks [ qindex ] ) ; if ( ( bp -> b_vflags & BV_BKGRDERR ) != 0 ) { bqrelse ( bp ) ; mtx_lock ( & bqlocks [ qindex ] ) ; nbp = TAILQ_FIRST ( & bufqueues [ qindex ] ) ; continue ; } bp -> b_flags |= B_INVAL ; brelse ( bp ) ; return ( 0 ) ; } mtx_unlock ( & bqlocks [ qindex ] ) ; return ( ENOBUFS ) ; }
buf_qrecycle:
      Free a buffer from the given bufqueue.
buf_qrecycle : Free a buffer from the given bufqueue .
/*
	 * Run scan, possibly freeing data and/or kva mappings on the fly
	 * depending.
	 */ /*
		 * Calculate next bp (we can only use it if we do not
		 * release the bqlock).
		 */ /*
		 * If we are defragging then we need a buffer with 
		 * some kva to reclaim.
		 */ /*
		 * Skip buffers with background writes in progress.
		 */ /*
		 * NOTE:  nbp is now entirely invalid.  We can only restart
		 * the scan from this point on.
		 */ /*
		 * Requeue the background write buffer with error and
		 * restart the scan.
		 */