diff options
Diffstat (limited to 'mm/zsmalloc.c')
-rw-r--r-- | mm/zsmalloc.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index 1227f8323e93..4b39e5eaf34f 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -1676,6 +1676,29 @@ static struct page *isolate_source_page(struct size_class *class) return page; } +/* + * + * Based on the number of unused allocated objects calculate + * and return the number of pages that we can free. + * + * Should be called under class->lock. + */ +static unsigned long zs_can_compact(struct size_class *class) +{ + unsigned long obj_wasted; + + if (!zs_stat_get(class, CLASS_ALMOST_EMPTY)) + return 0; + + obj_wasted = zs_stat_get(class, OBJ_ALLOCATED) - + zs_stat_get(class, OBJ_USED); + + obj_wasted /= get_maxobj_per_zspage(class->size, + class->pages_per_zspage); + + return obj_wasted * get_pages_per_zspage(class->size); +} + static unsigned long __zs_compact(struct zs_pool *pool, struct size_class *class) { @@ -1689,6 +1712,9 @@ static unsigned long __zs_compact(struct zs_pool *pool, BUG_ON(!is_first_page(src_page)); + if (!zs_can_compact(class)) + break; + cc.index = 0; cc.s_page = src_page; |