Since: "42c06a0e8ebe mm: kill frontswap" we no longer have a counter to tracks the number of zswap store failures. This makes it hard to investigate and monitor for zswap issues. This patch adds a global and a per-cgroup zswap store failure counter, as well as a dedicated debugfs counter for compression algorithm failure (which can happen for e.g when random data are passed to zswap). Signed-off-by: Nhat Pham <nphamcs@xxxxxxxxx> --- include/linux/vm_event_item.h | 1 + mm/memcontrol.c | 1 + mm/vmstat.c | 1 + mm/zswap.c | 18 ++++++++++++++---- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h index 8abfa1240040..7b2b117b193d 100644 --- a/include/linux/vm_event_item.h +++ b/include/linux/vm_event_item.h @@ -145,6 +145,7 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, #ifdef CONFIG_ZSWAP ZSWPIN, ZSWPOUT, + ZSWPOUT_FAIL, #endif #ifdef CONFIG_X86 DIRECT_MAP_LEVEL2_SPLIT, diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 61c0c46c2d62..0e247e72a379 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -593,6 +593,7 @@ static const unsigned int memcg_vm_event_stat[] = { #if defined(CONFIG_MEMCG_KMEM) && defined(CONFIG_ZSWAP) ZSWPIN, ZSWPOUT, + ZSWPOUT_FAIL, #endif #ifdef CONFIG_TRANSPARENT_HUGEPAGE THP_FAULT_ALLOC, diff --git a/mm/vmstat.c b/mm/vmstat.c index 359460deb377..85cc79449355 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1401,6 +1401,7 @@ const char * const vmstat_text[] = { #ifdef CONFIG_ZSWAP "zswpin", "zswpout", + "zswpout_fail", #endif #ifdef CONFIG_X86 "direct_map_level2_splits", diff --git a/mm/zswap.c b/mm/zswap.c index 37d2b1cb2ecb..38e6620f8b58 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -61,6 +61,8 @@ static u64 zswap_pool_limit_hit; static u64 zswap_written_back_pages; /* Store failed due to a reclaim failure after pool limit was reached */ static u64 zswap_reject_reclaim_fail; +/* Store failed due to compression algorithm failure */ +static u64 zswap_reject_compress_fail; /* Compressed page was too big for the allocator to (optimally) store */ static u64 zswap_reject_compress_poor; /* Store failed because underlying allocator could not get memory */ @@ -1213,10 +1215,10 @@ bool zswap_store(struct folio *folio) /* Large folios aren't supported */ if (folio_test_large(folio)) - return false; + goto out_reject; if (!zswap_enabled || !tree) - return false; + goto out_reject; /* * If this is a duplicate, it must be removed before attempting to store @@ -1309,8 +1311,10 @@ bool zswap_store(struct folio *folio) ret = crypto_wait_req(crypto_acomp_compress(acomp_ctx->req), &acomp_ctx->wait); dlen = acomp_ctx->req->dlen; - if (ret) + if (ret) { + zswap_reject_compress_fail++; goto put_dstmem; + } /* store */ zpool = zswap_find_zpool(entry); @@ -1377,8 +1381,12 @@ bool zswap_store(struct folio *folio) freepage: zswap_entry_cache_free(entry); reject: - if (objcg) + if (objcg) { + count_objcg_event(objcg, ZSWPOUT_FAIL); obj_cgroup_put(objcg); + } +out_reject: + count_vm_event(ZSWPOUT_FAIL); return false; shrink: @@ -1550,6 +1558,8 @@ static int zswap_debugfs_init(void) zswap_debugfs_root, &zswap_reject_alloc_fail); debugfs_create_u64("reject_kmemcache_fail", 0444, zswap_debugfs_root, &zswap_reject_kmemcache_fail); + debugfs_create_u64("reject_compress_fail", 0444, + zswap_debugfs_root, &zswap_reject_compress_fail); debugfs_create_u64("reject_compress_poor", 0444, zswap_debugfs_root, &zswap_reject_compress_poor); debugfs_create_u64("written_back_pages", 0444, -- 2.34.1