FreeBSD/sys/kern/vfs_bio.c
/* Initialize the buffer subsystem.  Called before use of any buffers. */
Initialize the buffer subsystem.  Called before use of any buffers.
Initialize the buffer subsystem . Called before use of any buffers .
void
bufinit(void)
{
	struct buf *bp;
	int i;
	CTASSERT(MAXBCACHEBUF >= MAXBSIZE);
	mtx_init(&bqlocks[QUEUE_DIRTY], "bufq dirty lock", NULL, MTX_DEF);
	mtx_init(&bqlocks[QUEUE_EMPTY], "bufq empty lock", NULL, MTX_DEF);
	for (i = QUEUE_CLEAN; i < QUEUE_CLEAN + CLEAN_QUEUES; i++)
		mtx_init(&bqlocks[i], "bufq clean lock", NULL, MTX_DEF);
	mtx_init(&rbreqlock, "runningbufspace lock", NULL, MTX_DEF);
	rw_init(&nblock, "needsbuffer lock");
	mtx_init(&bdlock, "buffer daemon lock", NULL, MTX_DEF);
	mtx_init(&bdirtylock, "dirty buf lock", NULL, MTX_DEF);
	for (i = 0; i < BUFFER_QUEUES; i++)
		TAILQ_INIT(&bufqueues[i]);
	unmapped_buf = (caddr_t)kva_alloc(MAXPHYS);
	for (i = 0; i < nbuf; i++) {
		bp = &buf[i];
		bzero(bp, sizeof *bp);
		bp->b_flags = B_INVAL;
		bp->b_rcred = NOCRED;
		bp->b_wcred = NOCRED;
		bp->b_qindex = QUEUE_EMPTY;
		bp->b_xflags = 0;
		bp->b_data = bp->b_kvabase = unmapped_buf;
		LIST_INIT(&bp->b_dep);
		BUF_LOCKINIT(bp);
		TAILQ_INSERT_TAIL(&bufqueues[QUEUE_EMPTY], bp, b_freelist);
#ifdef INVARIANTS
		bq_len[QUEUE_EMPTY]++;
#endif
	}
	maxbufspace = (long)nbuf * BKVASIZE;
	hibufspace = lmax(3 * maxbufspace / 4, maxbufspace - MAXBCACHEBUF * 10);
	lobufspace = (hibufspace / 20) * 19; 
	bufspacethresh = lobufspace + (hibufspace - lobufspace) / 2;
	hirunningspace = lmax(lmin(roundup(hibufspace / 64, MAXBCACHEBUF),
	    16 * 1024 * 1024), 1024 * 1024);
	lorunningspace = roundup((hirunningspace * 2) / 3, MAXBCACHEBUF);
	maxbufmallocspace = hibufspace / 20;
	hidirtybuffers = nbuf / 4 + 20;
	dirtybufthresh = hidirtybuffers * 9 / 10;
	numdirtybuffers = 0;
	while ((long)hidirtybuffers * BKVASIZE > 3 * hibufspace / 4) {
		hidirtybuffers >>= 1;
	}
	lodirtybuffers = hidirtybuffers / 2;
	lofreebuffers = MIN((nbuf / 25) + (20 * mp_ncpus), 128 * mp_ncpus);
	hifreebuffers = (3 * lofreebuffers) / 2;
	numfreebuffers = nbuf;
	bogus_page = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ |
	    VM_ALLOC_NORMAL | VM_ALLOC_WIRED);
	vmem_set_reclaim(buffer_arena, bufkva_reclaim);
	buf_zone = uma_zcache_create("buf free cache", sizeof(struct buf),
	    NULL, NULL, NULL, NULL, buf_import, buf_release, NULL, 0);
	clean_queues = MIN(howmany(maxbufspace, 256*1024*1024), CLEAN_QUEUES);
}
void bufinit ( void ) { struct buf * bp ; int i ; CTASSERT ( MAXBCACHEBUF >= MAXBSIZE ) ; mtx_init ( & bqlocks [ QUEUE_DIRTY ] , " " , NULL , MTX_DEF ) ; mtx_init ( & bqlocks [ QUEUE_EMPTY ] , " " , NULL , MTX_DEF ) ; for ( i = QUEUE_CLEAN ; i < QUEUE_CLEAN + CLEAN_QUEUES ; i ++ ) mtx_init ( & bqlocks [ i ] , " " , NULL , MTX_DEF ) ; mtx_init ( & rbreqlock , " " , NULL , MTX_DEF ) ; rw_init ( & nblock , " " ) ; mtx_init ( & bdlock , " " , NULL , MTX_DEF ) ; mtx_init ( & bdirtylock , " " , NULL , MTX_DEF ) ; for ( i = 0 ; i < BUFFER_QUEUES ; i ++ ) TAILQ_INIT ( & bufqueues [ i ] ) ; unmapped_buf = ( caddr_t ) kva_alloc ( MAXPHYS ) ; for ( i = 0 ; i < nbuf ; i ++ ) { bp = & buf [ i ] ; bzero ( bp , sizeof * bp ) ; bp -> b_flags = B_INVAL ; bp -> b_rcred = NOCRED ; bp -> b_wcred = NOCRED ; bp -> b_qindex = QUEUE_EMPTY ; bp -> b_xflags = 0 ; bp -> b_data = bp -> b_kvabase = unmapped_buf ; LIST_INIT ( & bp -> b_dep ) ; BUF_LOCKINIT ( bp ) ; TAILQ_INSERT_TAIL ( & bufqueues [ QUEUE_EMPTY ] , bp , b_freelist ) ; #ifdef INVARIANTS bq_len [ QUEUE_EMPTY ] ++ ; #endif } maxbufspace = ( long ) nbuf * BKVASIZE ; hibufspace = lmax ( 3 * maxbufspace / 4 , maxbufspace - MAXBCACHEBUF * 10 ) ; lobufspace = ( hibufspace / 20 ) * 19 ; bufspacethresh = lobufspace + ( hibufspace - lobufspace ) / 2 ; hirunningspace = lmax ( lmin ( roundup ( hibufspace / 64 , MAXBCACHEBUF ) , 16 * 1024 * 1024 ) , 1024 * 1024 ) ; lorunningspace = roundup ( ( hirunningspace * 2 ) / 3 , MAXBCACHEBUF ) ; maxbufmallocspace = hibufspace / 20 ; hidirtybuffers = nbuf / 4 + 20 ; dirtybufthresh = hidirtybuffers * 9 / 10 ; numdirtybuffers = 0 ; while ( ( long ) hidirtybuffers * BKVASIZE > 3 * hibufspace / 4 ) { hidirtybuffers >>= 1 ; } lodirtybuffers = hidirtybuffers / 2 ; lofreebuffers = MIN ( ( nbuf / 25 ) + ( 20 * mp_ncpus ) , 128 * mp_ncpus ) ; hifreebuffers = ( 3 * lofreebuffers ) / 2 ; numfreebuffers = nbuf ; bogus_page = vm_page_alloc ( NULL , 0 , VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL | VM_ALLOC_WIRED ) ; vmem_set_reclaim ( buffer_arena , bufkva_reclaim ) ; buf_zone = uma_zcache_create ( " " , sizeof ( struct buf ) , NULL , NULL , NULL , NULL , buf_import , buf_release , NULL , 0 ) ; clean_queues = MIN ( howmany ( maxbufspace , 256 * 1024 * 1024 ) , CLEAN_QUEUES ) ; }
Initialize the buffer subsystem.
Initialize the buffer subsystem .
/* next, make a null set of free lists */ /* finally, initialize each buffer header and stick on empty q */ /*
	 * maxbufspace is the absolute maximum amount of buffer space we are 
	 * allowed to reserve in KVM and in real terms.  The absolute maximum
	 * is nominally used by metadata.  hibufspace is the nominal maximum
	 * used by most other requests.  The differential is required to 
	 * ensure that metadata deadlocks don't occur.
	 *
	 * maxbufspace is based on BKVASIZE.  Allocating buffers larger then
	 * this may result in KVM fragmentation which is not handled optimally
	 * by the system. XXX This is less true with vmem.  We could use
	 * PAGE_SIZE.
	 */ /* 95% */ /*
	 * Note: The 16 MiB upper limit for hirunningspace was chosen
	 * arbitrarily and may need further tuning. It corresponds to
	 * 128 outstanding write IO requests (if IO size is 128 KiB),
	 * which fits with many RAID controllers' tagged queuing limits.
	 * The lower 1 MiB limit is the historical upper limit for
	 * hirunningspace.
	 */ /*
	 * Limit the amount of malloc memory since it is wired permanently into
	 * the kernel space.  Even though this is accounted for in the buffer
	 * allocation, we don't want the malloced region to grow uncontrolled.
	 * The malloc scheme improves memory utilization significantly on
	 * average (small) directories.
	 */ /*
	 * Reduce the chance of a deadlock occurring by limiting the number
	 * of delayed-write dirty buffers we allow to stack up.
	 */ /*
	 * To support extreme low-memory systems, make sure hidirtybuffers
	 * cannot eat up all available buffer space.  This occurs when our
	 * minimum cannot be met.  We try to size hidirtybuffers to 3/4 our
	 * buffer space assuming BKVASIZE'd buffers.
	 */ /*
	 * lofreebuffers should be sufficient to avoid stalling waiting on
	 * buf headers under heavy utilization.  The bufs in per-cpu caches
	 * are counted as free but will be unavailable to threads executing
	 * on other cpus.
	 *
	 * hifreebuffers is the free target for the bufspace daemon.  This
	 * should be set appropriately to limit work per-iteration.
	 */ /* Setup the kva and free list allocators. */ /*
	 * Size the clean queue according to the amount of buffer space.
	 * One queue per-256mb up to the max.  More queues gives better
	 * concurrency but less accurate LRU.
	 */