From nobody Sat Feb 7 15:02:33 2026 Received: from out-182.mta0.migadu.com (out-182.mta0.migadu.com [91.218.175.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2441F30DD00 for ; Thu, 5 Feb 2026 05:30:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770269459; cv=none; b=dx8HWFqaMvSFhFqxEA5ZulKTiXu5CfeKo1530fDs8vFWLst6oIQ8PQtyHgCjqGrNi1AvVCF/OQy6IDoAzZi/3dDKkTAmAIeVSRu85KxN7SBp+Zk75Xb6fJsM2FCd0ntYMImVvPLObMuVvQ7RCqNzkpZtS8DM9zfALU/M7x8yAgM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770269459; c=relaxed/simple; bh=MN4dodstiSzwVoQe0arnevGJiTIMdlCZ2Xm7aQ1cqdU=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=OuFgN45tXJa+cN+4D70i59Gjx/oiDxM3ki1JHM1JpTIi08ngqNLCumXj7UsbzgQhY4qmW4iPhOfjCxSGP3zHNqZDzPQiTrCItET98BVkGAeuYeSd/3dluSx6PVQVH12d0Fd54r3f0Prxp4bthpOvlK/alORDKzA7kMy5YfNxTSM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Ea1grlml; arc=none smtp.client-ip=91.218.175.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Ea1grlml" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1770269447; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=GgqfJdQjw9jeJ36Z1N0ESMnPon9eBH43wGJH8jQ18rY=; b=Ea1grlmlpc2e8TGxhyQfULCO/EY//nNMVo9ETJNbi3Irw3qu0wfzrfC9vtkfSXj+07s0HJ 0kO/NCx7ZavnuuCcB4ZuISd3uuAsmXmocWhOymciFIpNREGdZ1GJX2/AxRiVyI+ZvGg7SZ SFf2JUZzIOYrbum/+CFxaXd+WWdZ2IA= From: Jiayuan Chen To: linux-mm@kvack.org Cc: jiayuan.chen@linux.dev, Jiayuan Chen , Johannes Weiner , Michal Hocko , Roman Gushchin , Shakeel Butt , Muchun Song , Yosry Ahmed , Nhat Pham , Chengming Zhou , Andrew Morton , Nick Terrell , David Sterba , cgroups@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v1] mm: zswap: add per-memcg stat for incompressible pages Date: Thu, 5 Feb 2026 13:30:12 +0800 Message-ID: <20260205053013.25134-1-jiayuan.chen@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Jiayuan Chen The global zswap_stored_incompressible_pages counter was added in commit dca4437a5861 ("mm/zswap: store ------- 1. Add zswap_is_raw() helper (include/linux/zswap.h) - Abstract the PAGE_SIZE comparison logic for identifying raw entries - Keep the incompressible check in one place for maintainability 2. Add MEMCG_ZSWAP_RAW stat definition (include/linux/memcontrol.h, mm/memcontrol.c) - Add MEMCG_ZSWAP_RAW to memcg_stat_item enum - Register in memcg_stat_items[] and memory_stats[] arrays - Export as "zswpraw" in memory.stat 3. Update statistics accounting (mm/memcontrol.c, mm/zswap.c) - Track MEMCG_ZSWAP_RAW in obj_cgroup_charge/uncharge_zswap() - Use zswap_is_raw() helper in zswap.c for consistency Test ---- I wrote a simple test program[1] that allocates memory and compresses it with zstd, so kernel zswap cannot compress further. $ cgcreate -g memory:test $ cgexec -g memory:test ./test_zswpraw & $ cat /sys/fs/cgroup/test/memory.stat | grep zswp zswpraw 0 zswpin 0 zswpout 0 zswpwb 0 $ echo "100M" > /sys/fs/cgroup/test/memory.reclaim $ cat /sys/fs/cgroup/test/memory.stat | grep zswp zswpraw 104800256 zswpin 0 zswpout 51222 zswpwb 0 $ pkill test_zswpraw $ cat /sys/fs/cgroup/test/memory.stat | grep zswp zswpraw 0 zswpin 1 zswpout 51222 zswpwb 0 [1] https://gist.github.com/mrpre/00432c6154250326994fbeaf62e0e6f1 Signed-off-by: Jiayuan Chen --- include/linux/memcontrol.h | 1 + include/linux/zswap.h | 9 +++++++++ mm/memcontrol.c | 6 ++++++ mm/zswap.c | 6 +++--- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index b6c82c8f73e1..83d1328f81d1 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -39,6 +39,7 @@ enum memcg_stat_item { MEMCG_KMEM, MEMCG_ZSWAP_B, MEMCG_ZSWAPPED, + MEMCG_ZSWAP_RAW, MEMCG_NR_STAT, }; =20 diff --git a/include/linux/zswap.h b/include/linux/zswap.h index 30c193a1207e..94f84b154b71 100644 --- a/include/linux/zswap.h +++ b/include/linux/zswap.h @@ -7,6 +7,15 @@ =20 struct lruvec; =20 +/* + * Check if a zswap entry is stored in raw (uncompressed) form. + * This happens when compression doesn't reduce the size. + */ +static inline bool zswap_is_raw(size_t size) +{ + return size =3D=3D PAGE_SIZE; +} + extern atomic_long_t zswap_stored_pages; =20 #ifdef CONFIG_ZSWAP diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 007413a53b45..32fb801530a3 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -341,6 +341,7 @@ static const unsigned int memcg_stat_items[] =3D { MEMCG_KMEM, MEMCG_ZSWAP_B, MEMCG_ZSWAPPED, + MEMCG_ZSWAP_RAW, }; =20 #define NR_MEMCG_NODE_STAT_ITEMS ARRAY_SIZE(memcg_node_stat_items) @@ -1346,6 +1347,7 @@ static const struct memory_stat memory_stats[] =3D { #ifdef CONFIG_ZSWAP { "zswap", MEMCG_ZSWAP_B }, { "zswapped", MEMCG_ZSWAPPED }, + { "zswpraw", MEMCG_ZSWAP_RAW }, #endif { "file_mapped", NR_FILE_MAPPED }, { "file_dirty", NR_FILE_DIRTY }, @@ -5458,6 +5460,8 @@ void obj_cgroup_charge_zswap(struct obj_cgroup *objcg= , size_t size) memcg =3D obj_cgroup_memcg(objcg); mod_memcg_state(memcg, MEMCG_ZSWAP_B, size); mod_memcg_state(memcg, MEMCG_ZSWAPPED, 1); + if (zswap_is_raw(size)) + mod_memcg_state(memcg, MEMCG_ZSWAP_RAW, 1); rcu_read_unlock(); } =20 @@ -5481,6 +5485,8 @@ void obj_cgroup_uncharge_zswap(struct obj_cgroup *obj= cg, size_t size) memcg =3D obj_cgroup_memcg(objcg); mod_memcg_state(memcg, MEMCG_ZSWAP_B, -size); mod_memcg_state(memcg, MEMCG_ZSWAPPED, -1); + if (zswap_is_raw(size)) + mod_memcg_state(memcg, MEMCG_ZSWAP_RAW, -1); rcu_read_unlock(); } =20 diff --git a/mm/zswap.c b/mm/zswap.c index 3d2d59ac3f9c..54ab4d126f64 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -723,7 +723,7 @@ static void zswap_entry_free(struct zswap_entry *entry) obj_cgroup_uncharge_zswap(entry->objcg, entry->length); obj_cgroup_put(entry->objcg); } - if (entry->length =3D=3D PAGE_SIZE) + if (zswap_is_raw(entry->length)) atomic_long_dec(&zswap_stored_incompressible_pages); zswap_entry_cache_free(entry); atomic_long_dec(&zswap_stored_pages); @@ -941,7 +941,7 @@ static bool zswap_decompress(struct zswap_entry *entry,= struct folio *folio) zs_obj_read_sg_begin(pool->zs_pool, entry->handle, input, entry->length); =20 /* zswap entries of length PAGE_SIZE are not compressed. */ - if (entry->length =3D=3D PAGE_SIZE) { + if (zswap_is_raw(entry->length)) { WARN_ON_ONCE(input->length !=3D PAGE_SIZE); memcpy_from_sglist(kmap_local_folio(folio, 0), input, 0, PAGE_SIZE); dlen =3D PAGE_SIZE; @@ -1448,7 +1448,7 @@ static bool zswap_store_page(struct page *page, obj_cgroup_charge_zswap(objcg, entry->length); } atomic_long_inc(&zswap_stored_pages); - if (entry->length =3D=3D PAGE_SIZE) + if (zswap_is_raw(entry->length)) atomic_long_inc(&zswap_stored_incompressible_pages); =20 /* --=20 2.43.0