summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/page-flags.h8
-rw-r--r--mm/debug.c3
-rw-r--r--mm/vmscan.c12
-rw-r--r--mm/zcache.c13
4 files changed, 35 insertions, 1 deletions
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index bb53c7b86315..4b115168607f 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -108,6 +108,9 @@ enum pageflags {
PG_young,
PG_idle,
#endif
+#ifdef CONFIG_ZCACHE
+ PG_was_active,
+#endif
__NR_PAGEFLAGS,
/* Filesystems */
@@ -224,6 +227,11 @@ PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked)
__SETPAGEFLAG(SwapBacked, swapbacked)
__PAGEFLAG(SlobFree, slob_free)
+#ifdef CONFIG_ZCACHE
+PAGEFLAG(WasActive, was_active)
+#else
+PAGEFLAG_FALSE(WasActive)
+#endif
/*
* Private page markings that may be used by the filesystem that owns the page
diff --git a/mm/debug.c b/mm/debug.c
index 668aa35191ca..5cf26f8c69a3 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -47,6 +47,9 @@ static const struct trace_print_flags pageflag_names[] = {
{1UL << PG_young, "young" },
{1UL << PG_idle, "idle" },
#endif
+#ifdef CONFIG_ZCACHE
+ {1UL << PG_was_active, "was_active" },
+#endif
};
static void dump_flags(unsigned long flags,
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 3f702c2f9d58..9c92f7d1be90 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1575,6 +1575,7 @@ putback_inactive_pages(struct lruvec *lruvec, struct list_head *page_list)
while (!list_empty(page_list)) {
struct page *page = lru_to_page(page_list);
int lru;
+ int file;
VM_BUG_ON_PAGE(PageLRU(page), page);
list_del(&page->lru);
@@ -1591,8 +1592,11 @@ putback_inactive_pages(struct lruvec *lruvec, struct list_head *page_list)
lru = page_lru(page);
add_page_to_lru_list(page, lruvec, lru);
+ file = is_file_lru(lru);
+ if (IS_ENABLED(CONFIG_ZCACHE))
+ if (file)
+ SetPageWasActive(page);
if (is_active_lru(lru)) {
- int file = is_file_lru(lru);
int numpages = hpage_nr_pages(page);
reclaim_stat->recent_rotated[file] += numpages;
}
@@ -1917,6 +1921,12 @@ static void shrink_active_list(unsigned long nr_to_scan,
}
ClearPageActive(page); /* we are de-activating */
+ if (IS_ENABLED(CONFIG_ZCACHE))
+ /*
+ * For zcache to know whether the page is from active
+ * file list
+ */
+ SetPageWasActive(page);
list_add(&page->lru, &l_inactive);
}
diff --git a/mm/zcache.c b/mm/zcache.c
index 28c070b99e06..322b8f836a49 100644
--- a/mm/zcache.c
+++ b/mm/zcache.c
@@ -68,6 +68,7 @@ static u64 zcache_dup_entry;
static u64 zcache_zbud_alloc_fail;
static u64 zcache_evict_zpages;
static u64 zcache_evict_filepages;
+static u64 zcache_inactive_pages_refused;
static u64 zcache_reclaim_fail;
static u64 zcache_pool_shrink;
static u64 zcache_pool_shrink_fail;
@@ -648,6 +649,17 @@ static void zcache_store_page(int pool_id, struct cleancache_filekey key,
struct zcache_pool *zpool = zcache.pools[pool_id];
+ /*
+ * Zcache will be ineffective if the compressed memory pool is full with
+ * compressed inactive file pages and most of them will never be used
+ * again.
+ * So we refuse to compress pages that are not from active file list.
+ */
+ if (!PageWasActive(page)) {
+ zcache_inactive_pages_refused++;
+ return;
+ }
+
if (zcache_is_full()) {
zcache_pool_limit_hit++;
if (zbud_reclaim_page(zpool->pool, 8)) {
@@ -762,6 +774,7 @@ map:
/* update stats */
atomic_dec(&zcache_stored_pages);
zpool->size = zbud_get_pool_size(zpool->pool);
+ SetPageWasActive(page);
return ret;
}