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) | |||
1676 | return page; | 1676 | return page; |
1677 | } | 1677 | } |
1678 | 1678 | ||
1679 | /* | ||
1680 | * | ||
1681 | * Based on the number of unused allocated objects calculate | ||
1682 | * and return the number of pages that we can free. | ||
1683 | * | ||
1684 | * Should be called under class->lock. | ||
1685 | */ | ||
1686 | static unsigned long zs_can_compact(struct size_class *class) | ||
1687 | { | ||
1688 | unsigned long obj_wasted; | ||
1689 | |||
1690 | if (!zs_stat_get(class, CLASS_ALMOST_EMPTY)) | ||
1691 | return 0; | ||
1692 | |||
1693 | obj_wasted = zs_stat_get(class, OBJ_ALLOCATED) - | ||
1694 | zs_stat_get(class, OBJ_USED); | ||
1695 | |||
1696 | obj_wasted /= get_maxobj_per_zspage(class->size, | ||
1697 | class->pages_per_zspage); | ||
1698 | |||
1699 | return obj_wasted * get_pages_per_zspage(class->size); | ||
1700 | } | ||
1701 | |||
1679 | static unsigned long __zs_compact(struct zs_pool *pool, | 1702 | static unsigned long __zs_compact(struct zs_pool *pool, |
1680 | struct size_class *class) | 1703 | struct size_class *class) |
1681 | { | 1704 | { |
@@ -1689,6 +1712,9 @@ static unsigned long __zs_compact(struct zs_pool *pool, | |||
1689 | 1712 | ||
1690 | BUG_ON(!is_first_page(src_page)); | 1713 | BUG_ON(!is_first_page(src_page)); |
1691 | 1714 | ||
1715 | if (!zs_can_compact(class)) | ||
1716 | break; | ||
1717 | |||
1692 | cc.index = 0; | 1718 | cc.index = 0; |
1693 | cc.s_page = src_page; | 1719 | cc.s_page = src_page; |
1694 | 1720 | ||