FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
/*
 * The buffer, supplied as the first argument, needs a data block. If we
 * are hitting the hard limit for the cache size, we must sleep, waiting
 * for the eviction thread to catch up. If we're past the target size
 * but below the hard limit, we'll only signal the reclaim thread and
 * continue on.
 */
The buffer, supplied as the first argument, needs a data block. If we
are hitting the hard limit for the cache size, we must sleep, waiting
for the eviction thread to catch up. If we're past the target size
but below the hard limit, we'll only signal the reclaim thread and
continue on.
The buffer supplied as the first argument needs a data block . If we are hitting the hard limit for the cache size we must sleep waiting for the eviction thread to catch up . If we ' re past the target size but below the hard limit we ' ll only signal the reclaim thread and continue on .
static void
arc_get_data_buf(arc_buf_t *buf)
{
	arc_state_t		*state = buf->b_hdr->b_l1hdr.b_state;
	uint64_t		size = buf->b_hdr->b_size;
	arc_buf_contents_t	type = arc_buf_type(buf->b_hdr);
	arc_adapt(size, state);
	if (arc_is_overflowing()) {
		mutex_enter(&arc_reclaim_lock);
		if (arc_is_overflowing()) {
			cv_signal(&arc_reclaim_thread_cv);
			cv_wait(&arc_reclaim_waiters_cv, &arc_reclaim_lock);
		}
		mutex_exit(&arc_reclaim_lock);
	}
	if (type == ARC_BUFC_METADATA) {
		buf->b_data = zio_buf_alloc(size);
		arc_space_consume(size, ARC_SPACE_META);
	} else {
		ASSERT(type == ARC_BUFC_DATA);
		buf->b_data = zio_data_buf_alloc(size);
		arc_space_consume(size, ARC_SPACE_DATA);
	}
	if (!GHOST_STATE(buf->b_hdr->b_l1hdr.b_state)) {
		arc_buf_hdr_t *hdr = buf->b_hdr;
		arc_state_t *state = hdr->b_l1hdr.b_state;
		(void) refcount_add_many(&state->arcs_size, size, buf);
		if (multilist_link_active(&hdr->b_l1hdr.b_arc_node)) {
			ASSERT(refcount_is_zero(&hdr->b_l1hdr.b_refcnt));
			atomic_add_64(&hdr->b_l1hdr.b_state->arcs_lsize[type],
			    size);
		}
		if (arc_size < arc_c && hdr->b_l1hdr.b_state == arc_anon &&
		    (refcount_count(&arc_anon->arcs_size) +
		    refcount_count(&arc_mru->arcs_size) > arc_p))
			arc_p = MIN(arc_c, arc_p + size);
	}
	ARCSTAT_BUMP(arcstat_allocated);
}
static void arc_get_data_buf ( arc_buf_t * buf ) { arc_state_t * state = buf -> b_hdr -> b_l1hdr . b_state ; uint64_t size = buf -> b_hdr -> b_size ; arc_buf_contents_t type = arc_buf_type ( buf -> b_hdr ) ; arc_adapt ( size , state ) ; if ( arc_is_overflowing ( ) ) { mutex_enter ( & arc_reclaim_lock ) ; if ( arc_is_overflowing ( ) ) { cv_signal ( & arc_reclaim_thread_cv ) ; cv_wait ( & arc_reclaim_waiters_cv , & arc_reclaim_lock ) ; } mutex_exit ( & arc_reclaim_lock ) ; } if ( type == ARC_BUFC_METADATA ) { buf -> b_data = zio_buf_alloc ( size ) ; arc_space_consume ( size , ARC_SPACE_META ) ; } else { ASSERT ( type == ARC_BUFC_DATA ) ; buf -> b_data = zio_data_buf_alloc ( size ) ; arc_space_consume ( size , ARC_SPACE_DATA ) ; } if ( ! GHOST_STATE ( buf -> b_hdr -> b_l1hdr . b_state ) ) { arc_buf_hdr_t * hdr = buf -> b_hdr ; arc_state_t * state = hdr -> b_l1hdr . b_state ; ( void ) refcount_add_many ( & state -> arcs_size , size , buf ) ; if ( multilist_link_active ( & hdr -> b_l1hdr . b_arc_node ) ) { ASSERT ( refcount_is_zero ( & hdr -> b_l1hdr . b_refcnt ) ) ; atomic_add_64 ( & hdr -> b_l1hdr . b_state -> arcs_lsize [ type ] , size ) ; } if ( arc_size < arc_c && hdr -> b_l1hdr . b_state == arc_anon && ( refcount_count ( & arc_anon -> arcs_size ) + refcount_count ( & arc_mru -> arcs_size ) > arc_p ) ) arc_p = MIN ( arc_c , arc_p + size ) ; } ARCSTAT_BUMP ( arcstat_allocated ) ; }
The buffer, supplied as the first argument, needs a data block.
The buffer supplied as the first argument needs a data block .
/*
	 * If arc_size is currently overflowing, and has grown past our
	 * upper limit, we must be adding data faster than the evict
	 * thread can evict. Thus, to ensure we don't compound the
	 * problem by adding more data and forcing arc_size to grow even
	 * further past it's target size, we halt and wait for the
	 * eviction thread to catch up.
	 *
	 * It's also possible that the reclaim thread is unable to evict
	 * enough buffers to get arc_size below the overflow limit (e.g.
	 * due to buffers being un-evictable, or hash lock collisions).
	 * In this case, we want to proceed regardless if we're
	 * overflowing; thus we don't use a while loop here.
	 */ /*
		 * Now that we've acquired the lock, we may no longer be
		 * over the overflow limit, lets check.
		 *
		 * We're ignoring the case of spurious wake ups. If that
		 * were to happen, it'd let this thread consume an ARC
		 * buffer before it should have (i.e. before we're under
		 * the overflow limit and were signalled by the reclaim
		 * thread). As long as that is a rare occurrence, it
		 * shouldn't cause any harm.
		 */ /*
	 * Update the state size.  Note that ghost states have a
	 * "ghost size" and so don't need to be updated.
	 */ /*
		 * If this is reached via arc_read, the link is
		 * protected by the hash lock. If reached via
		 * arc_buf_alloc, the header should not be accessed by
		 * any other thread. And, if reached via arc_read_done,
		 * the hash lock will protect it if it's found in the
		 * hash table; otherwise no other thread should be
		 * trying to [add|remove]_reference it.
		 */ /*
		 * If we are growing the cache, and we are adding anonymous
		 * data, and we have outgrown arc_p, update arc_p
		 */