Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c (revision 232157) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c (working copy) @@ -143,8 +143,10 @@ extern uint64_t zfs_write_limit_max; extern kmutex_t zfs_write_limit_lock; +#ifdef sun #define ARC_REDUCE_DNLC_PERCENT 3 uint_t arc_reduce_dnlc_percent = ARC_REDUCE_DNLC_PERCENT; +#endif typedef enum arc_reclaim_strategy { ARC_RECLAIM_AGGR, /* Aggressive reclaim strategy */ @@ -2106,6 +2108,26 @@ } static void +arc_adjust_meta(int64_t adjustment) +{ + int64_t delta; + + if (adjustment > 0 && arc_mru->arcs_lsize[ARC_BUFC_METADATA] > 0) { + delta = MIN(arc_mru->arcs_lsize[ARC_BUFC_METADATA], adjustment); + (void) arc_evict(arc_mru, 0, delta, FALSE, + ARC_BUFC_METADATA); + adjustment -= delta; + } + + if (adjustment > 0 && arc_mfu->arcs_lsize[ARC_BUFC_METADATA] > 0) { + int64_t delta = MIN(adjustment, + arc_mfu->arcs_lsize[ARC_BUFC_METADATA]); + (void) arc_evict(arc_mfu, 0, delta, FALSE, + ARC_BUFC_METADATA); + } +} + +static void arc_do_user_evicts(void) { static arc_buf_t *tmp_arc_eviction_list; @@ -2292,6 +2314,7 @@ kmem_cache_t *prev_data_cache = NULL; #ifdef _KERNEL +#ifdef sun if (arc_meta_used >= arc_meta_limit) { /* * We are exceeding our meta-data cache limit. @@ -2299,6 +2322,7 @@ */ dnlc_reduce_cache((void *)(uintptr_t)arc_reduce_dnlc_percent); } +#endif #if defined(__i386) /* * Reclaim unused memory from all kmem caches. @@ -2334,6 +2358,7 @@ clock_t growtime = 0; arc_reclaim_strategy_t last_reclaim = ARC_RECLAIM_CONS; callb_cpr_t cpr; + int64_t prune; CALLB_CPR_INIT(&cpr, &arc_reclaim_thr_lock, callb_generic_cpr, FTAG); @@ -2372,6 +2397,11 @@ arc_no_grow = FALSE; } + prune = (int64_t)arc_meta_used - (int64_t)arc_meta_limit; + /* Keep meta data usage within limits */ + if (prune > 0) + arc_adjust_meta(prune); + arc_adjust(); if (arc_eviction_list != NULL) @@ -2567,6 +2597,11 @@ if (type == ARC_BUFC_METADATA) { buf->b_data = zio_buf_alloc(size); arc_space_consume(size, ARC_SPACE_DATA); + /* + * If we are unable to recycle an existing meta buffer + * signal the reclaim thread. + */ + cv_signal(&arc_reclaim_thr_cv); } else { ASSERT(type == ARC_BUFC_DATA); buf->b_data = zio_data_buf_alloc(size);