X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Farc.c;h=eb5304a82a8cfb592758fcb585ef78ef87c8a77d;hb=da88a7fbe8876437c25f1006f91ca5595659b8d2;hp=9ca8ad17d75d37d4a4d11f138ac9cc0b99133ebd;hpb=7cb67b45f33fd7a61af24c675c7347eb5264b38c;p=zfs.git diff --git a/module/zfs/arc.c b/module/zfs/arc.c index 9ca8ad1..eb5304a 100644 --- a/module/zfs/arc.c +++ b/module/zfs/arc.c @@ -180,6 +180,7 @@ unsigned long zfs_arc_meta_limit = 0; int zfs_arc_grow_retry = 0; int zfs_arc_shrink_shift = 0; int zfs_arc_p_min_shift = 0; +int zfs_arc_reduce_dnlc_percent = 0; /* * Note that buffers can be in one of 6 states: @@ -2084,14 +2085,16 @@ arc_kmem_reap_now(arc_reclaim_strategy_t strat) kmem_cache_t *prev_data_cache = NULL; extern kmem_cache_t *zio_buf_cache[]; extern kmem_cache_t *zio_data_buf_cache[]; - #ifdef _KERNEL - if (arc_meta_used >= arc_meta_limit) { + int retry = 0; + + while ((arc_meta_used >= arc_meta_limit) && (retry < 10)) { /* * We are exceeding our meta-data cache limit. * Purge some DNLC entries to release holds on meta-data. */ dnlc_reduce_cache((void *)(uintptr_t)arc_reduce_dnlc_percent); + retry++; } #if defined(__i386) /* @@ -2157,6 +2160,10 @@ arc_reclaim_thread(void) arc_no_grow = FALSE; } + /* Keep meta data usage within limits */ + if (arc_meta_used >= arc_meta_limit) + arc_kmem_reap_now(ARC_RECLAIM_CONS); + arc_adjust(); if (arc_eviction_list != NULL) @@ -2189,15 +2196,20 @@ SPL_SHRINKER_CALLBACK_PROTO(arc_shrinker_func, cb, nr_to_scan, gfp_mask) arc_reclaim_strategy_t strategy; int arc_reclaim; - /* Not allowed to perform filesystem reclaim */ - if (!(gfp_mask & __GFP_FS)) - return (-1); - /* Return number of reclaimable pages based on arc_shrink_shift */ - arc_reclaim = btop((arc_size - arc_c_min)) >> arc_shrink_shift; + arc_reclaim = MAX(btop(((int64_t)arc_size - (int64_t)arc_c_min)) + >> arc_shrink_shift, 0); if (nr_to_scan == 0) return (arc_reclaim); + /* Prevent reclaim below arc_c_min */ + if (arc_reclaim <= 0) + return (-1); + + /* Not allowed to perform filesystem reclaim */ + if (!(gfp_mask & __GFP_FS)) + return (-1); + /* Reclaim in progress */ if (mutex_tryenter(&arc_reclaim_thr_lock) == 0) return (-1); @@ -2211,7 +2223,8 @@ SPL_SHRINKER_CALLBACK_PROTO(arc_shrinker_func, cb, nr_to_scan, gfp_mask) } arc_kmem_reap_now(strategy); - arc_reclaim = btop((arc_size - arc_c_min)) >> arc_shrink_shift; + arc_reclaim = MAX(btop(((int64_t)arc_size - (int64_t)arc_c_min)) + >> arc_shrink_shift, 0); mutex_exit(&arc_reclaim_thr_lock); return (arc_reclaim); @@ -3583,6 +3596,9 @@ arc_init(void) if (zfs_arc_p_min_shift > 0) arc_p_min_shift = zfs_arc_p_min_shift; + if (zfs_arc_reduce_dnlc_percent > 0) + arc_reduce_dnlc_percent = zfs_arc_reduce_dnlc_percent; + /* if kmem_flags are set, lets try to use less memory */ if (kmem_debugging()) arc_c = arc_c / 2; @@ -4757,12 +4773,25 @@ EXPORT_SYMBOL(arc_read); EXPORT_SYMBOL(arc_buf_remove_ref); EXPORT_SYMBOL(arc_getbuf_func); -module_param(zfs_arc_min, ulong, 0644); -MODULE_PARM_DESC(zfs_arc_min, "Minimum arc size"); +module_param(zfs_arc_min, ulong, 0444); +MODULE_PARM_DESC(zfs_arc_min, "Min arc size"); -module_param(zfs_arc_max, ulong, 0644); -MODULE_PARM_DESC(zfs_arc_max, "Maximum arc size"); +module_param(zfs_arc_max, ulong, 0444); +MODULE_PARM_DESC(zfs_arc_max, "Max arc size"); -module_param(zfs_arc_meta_limit, ulong, 0644); +module_param(zfs_arc_meta_limit, ulong, 0444); MODULE_PARM_DESC(zfs_arc_meta_limit, "Meta limit for arc size"); + +module_param(zfs_arc_reduce_dnlc_percent, int, 0444); +MODULE_PARM_DESC(zfs_arc_reduce_dnlc_percent, "Meta reclaim percentage"); + +module_param(zfs_arc_grow_retry, int, 0444); +MODULE_PARM_DESC(zfs_arc_grow_retry, "Seconds before growing arc size"); + +module_param(zfs_arc_shrink_shift, int, 0444); +MODULE_PARM_DESC(zfs_arc_shrink_shift, "log2(fraction of arc to reclaim)"); + +module_param(zfs_arc_p_min_shift, int, 0444); +MODULE_PARM_DESC(zfs_arc_p_min_shift, "arc_c shift to calc min/max arc_p"); + #endif