From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=209.85.128.177 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1792563525; b=zCNMSt6DmH9cxgFLC4MzZr2OFP4d8fP5wq8ecU5yzVoq9+fEGWcX7i2oLgmuha/9FDeQ pFY7XJ9wZOIghNAvJAnOsufbGtinpffE31oAP+TXWZEUN7cW2mNMKGt+l7JuGENeIkwhi Mz2d5HrOAmjkxHuOd7DkeLPF8ndvHhh7edCc6Kl2BYGfCdQHHgF1GAdYdi4f3pWiIV7AR HnDRsbYQ8xPGqcoPMw1JIIRvWnbLOkKfOOv12ugYnGhY4cl2h7T29xqmu0MfQiYpeBV1s QyZfqOp+LQthi1s5ENQ9589l74y91g+meLS8R5OgIB+DH0BHyvnLaqhAnWlnoFbzaxQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1792563525; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Gm-Gg:X-Received:Received: From:To:Cc:Subject:Date:Message-ID:X-Mailer:In-Reply-To:References: MIME-Version:Content-Transfer-Encoding; bh=58YpRd/cYSDDR/L9xMCDYI7HHr4Po+wYl+qR/bSF0HE=; b=AYuRGNfipMXB82suYQugQxigz4mZ3WdafnkEcFYoshuDG7HCNyXJwKpqgtD1HSTX4PA2 kOMklJm14IQ9CjiEC8pW54ENgXULDZL3skjzvqvhhbt/jH8zlQROHeacjgSjr3MP/C8ux B1HMn84BME2RwzFS4ixZkpnuajoTot+yW3AhWqdmEd8cNtMa1dlGtASFEf+BBiHWLkTWt y8JwpeT9eEzc0N6emPIOv683s0zLrBVY9ITb9Zw+YxSSsC+tYHfmxCZGuMIX8jozLpykn eyYfFFoeiOMKeQBTPkQbnwt5Qlw4HkDsgl9cHWs6xTP3GCBMOUkFsSJZ1YyAdZzPmyg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=etkOF1j+; arc=none smtp.remote-ip=209.85.128.177 Received: from mail-yw1-f177.google.com (mail-yw1-f177.google.com [209.85.128.177]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 83C65606A32A for ; Wed, 21 Oct 2026 06:18:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 83C65606A32A Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=etkOF1j+ Received: by mail-yw1-f177.google.com with SMTP id 00721157ae682-8b06c0794cfso3971377b3.0 for ; Tue, 20 Oct 2026 23:18:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792563524; x=1793168324; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=58YpRd/cYSDDR/L9xMCDYI7HHr4Po+wYl+qR/bSF0HE=; b=etkOF1j+GA4cvkPIGm8wheqU7IVigFTXEuRubL97q+xt5XSeKPU4oEMKjGyAb6CWZS 12JlHE4s6Xg1jDNKCrrOwYXyq1PJ2TifbU0fTlfi8LSJERCH8fkTke8EylL3UtsvKBf+ ME42rV589WP2ZLPHtbzJ2R8XgIxDnokgCY6DGcVn/9rLr1U07EanhZp+Jla5CE2glOkw /ijKs1nMN1Igi41QCAzVtr0NaCWT8DOlMe8zkwmZygLsDBmJEYKyyK4y7+yjKRGYCEgm f3xZTf4K8s0ycGcbNE9Daqs9O8I42q5S6HR4DtnxTC3y7tJAJAe40SrcF5/z6CW8o3kZ EJJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792563524; x=1793168324; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=58YpRd/cYSDDR/L9xMCDYI7HHr4Po+wYl+qR/bSF0HE=; b=HbkMSnCT52jQ7JeMVqOBh9KcZ1fl+bADCyarHuD4kSa2IYs8Wze0s7XbrtBMtgquaf 2vl4QV2Tpll3/NYq5oXspISMR1uAzOgo5HHcihH/pR8Fa8kj1Amexa/Y4cQaOd1mLzaE wHafqsvSAKNkAu50EnjKu7t+brtJbL4QGcw6zhNf67zXxDUPdtJ521I9WNiZ9jf3f2Bn ro/f8BjJMxKrdhTxs5xd2A+KMNnDuPbzueF0bQBocPHn3Orn8JDMpeB2iVaMVjW/PYmh 0hu+ci5q6xCrCXQ8wIROc1COEK/PMUPO0yTFGdtmWUXysSHH4y2doBIoSEdjdraCxWvp MBPA== X-Forwarded-Encrypted: i=1; AKwUvBxmQ2sp1WzOLMM30rSNTWEHGu8JmPIcpTxgaLvRgK5gPRU5Eo1IbY1gb8PzDrdo6B6iDjrWshm2Of4=@vger.kernel.org X-Gm-Message-State: AFq9FYKnCOrunQIMHWw/bOtlNprm2VsoWbScPiE9VbdFUrym5L3NNvyk PaAkySlXgG0CC9akL/azBnkOas524ZT9M1LBu/WRh63mbCVlJgnmr+kU X-Gm-Gg: AYBFou2ntOrlxPJCrAnMZKaZfqMnUYjKoec0cvCsLNWWPQLfYwAPrIfcoPk1GuYG0IG ApgIDynmF6Eh7JNYqpUem6pbVuUoGBl0kQ1AVTmOBb7FBQQjVniyiLQqcKdrJpEqt56QjDqA2Pe 2NQ23xYGZ4ACHuC6w0jkwZzpJlsqOavbkVl32KYvzYoXbJIKFSzcDRSSOcKPBl5HX/GZfv807BL zAi57zqMEIC7OZvGYUbIPioil+ii8RMJuRgdl+l6TKBgb6zRKFLf4q0VkEq2133bUqeFm18SC9T PpV1B3GL1ca2l1oHqVcNoa04BCghN2/oz8miuQDiS43IrozKBam7BCEIWTKy7TZtbx+eayTvn1s HAl7KIx5/HaYH3frUEeayGjUB2XPePSPoR1066hs6WLGrBZrM0UBdNiglEAeboL0aU+D6GM4QCn 4WjTv6EdMoxq3VcE7rtHg+RFTNw8d28rf7xFMTdLZiKj6cx5p6tD6NyD8jQl9jl5ohCA1ivItO+ G5p1pOqdpMiqeG09rRYHyZPa8YhDASGzNZCSRaqcctnrsVuPEZxyrCEhgMEHdQG+tmXOJBy9FxW 9w/herUpHpuVX6Q0AlVaU37DocLQijmWHjY8h8G8Rkhxx93txbhL7ch+wkyR1keYG8PRVdoHlRJ lr4JFdHSN6Q== X-Received: by 2002:a05:690e:1489:b0:677:bf19:f09b with SMTP id 956f58d0204a3-67a0e0331abmr712381d50.13.1792563524445; Tue, 20 Oct 2026 23:18:44 -0700 (PDT) Received: from localhost ([2a03:2880:10ff:5c::]) by smtp.gmail.com with ESMTPSA id 956f58d0204a3-67a0e1851cfsm653829d50.1.2026.10.20.23.18.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Oct 2026 23:18:42 -0700 (PDT) From: Nhat Pham To: akpm@linux-foundation.org Cc: chrisl@kernel.org, kasong@tencent.com, hannes@cmpxchg.org, mhocko@kernel.org, roman.gushchin@linux.dev, shakeel.butt@linux.dev, yosry@kernel.org, david@kernel.org, muchun.song@linux.dev, shikemeng@huaweicloud.com, baoquan.he@linux.dev, baohua@kernel.org, youngjun.park@lge.com, chengming.zhou@linux.dev, ljs@kernel.org, liam@infradead.org, vbabka@kernel.org, rppt@kernel.org, surenb@google.com, qi.zheng@linux.dev, axelrasmussen@google.com, yuanchu@google.com, weixugc@google.com, riel@surriel.com, gourry@gourry.net, haowenchao22@gmail.com, corbet@lwn.net, hughd@google.com, baolin.wang@linux.alibaba.com, tj@kernel.org, mkoutny@suse.com, skhan@linuxfoundation.org, rdunlap@infradead.org, kunwu.chan@linux.dev, kernel-team@meta.com, nphamcs@gmail.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, cgroups@vger.kernel.org Subject: [PATCH v6 11/12] mm, swap: add vmstat and memcg counters for vswap Date: Tue, 20 Oct 2026 23:18:36 -0700 Message-ID: <20261021061837.1569125-2-nphamcs@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261021060323.553433-1-nphamcs@gmail.com> References: <20261021060323.553433-1-nphamcs@gmail.com> X-Mailing-List: linux-doc@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add nr_vswap to /proc/vmstat and vswap to cgroup's memory.stat to report virtual swap usage. These counters help diagnose swapping issues. Userspace can also use vswap as a component of a workload's logical memory footprint when making policy decisions. Suggested-by: Johannes Weiner Signed-off-by: Nhat Pham --- .../admin-guide/cgroup-v1/memory.rst | 1 + Documentation/admin-guide/cgroup-v2.rst | 3 +++ include/linux/memcontrol.h | 1 + include/linux/swap.h | 1 + include/linux/vmstat.h | 3 +++ mm/memcontrol-v1.c | 6 +++++- mm/memcontrol.c | 20 +++++++++++++++---- mm/swapfile.c | 10 +++++++--- mm/vmstat.c | 6 ++++++ 9 files changed, 43 insertions(+), 8 deletions(-) diff --git a/Documentation/admin-guide/cgroup-v1/memory.rst b/Documentation/admin-guide/cgroup-v1/memory.rst index 2a67356d25a0..8ca9ef2bca9f 100644 --- a/Documentation/admin-guide/cgroup-v1/memory.rst +++ b/Documentation/admin-guide/cgroup-v1/memory.rst @@ -555,6 +555,7 @@ memory.stat file includes following statistics: cgroup. swap # of bytes of physical swap usage swapcached # of bytes of swap cached in memory + vswap # of bytes of virtual swap usage dirty # of bytes that are waiting to get written back to the disk. writeback # of bytes of file/anon cache that are queued for syncing to disk. diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index 623d29ea8c41..b1f97a61a1dc 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -1633,6 +1633,9 @@ The following nested keys are defined. against memory usage, and against swap usage when the swap entry has physical backing. + vswap + Amount of virtual swap usage. + anon_thp Amount of memory used in anonymous mappings backed by transparent hugepages diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index b9072a3c9a2a..99beb676d8e7 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -41,6 +41,7 @@ enum memcg_stat_item { MEMCG_ZSWAP_B, MEMCG_ZSWAPPED, MEMCG_ZSWAP_INCOMP, + MEMCG_VSWAP, MEMCG_NR_STAT, }; diff --git a/include/linux/swap.h b/include/linux/swap.h index a05189c92dae..891442264ca9 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -371,6 +371,7 @@ bool current_is_kswapd(void); #ifdef CONFIG_SWAP bool mem_cgroup_can_vswap(struct mem_cgroup *memcg); +unsigned long vswap_usage_in_pages(void); int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, unsigned long nr_pages, sector_t start_block); diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index 5b31d8e7ae40..37aff1ffac08 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h @@ -33,6 +33,9 @@ enum vm_stat_item { NR_DIRTY_BG_THRESHOLD, NR_MEMMAP_PAGES, /* page metadata allocated through buddy allocator */ NR_MEMMAP_BOOT_PAGES, /* page metadata allocated through boot allocator */ +#ifdef CONFIG_SWAP + NR_VSWAP, /* pages occupying a virtual swap slot */ +#endif NR_VM_STAT_ITEMS, }; diff --git a/mm/memcontrol-v1.c b/mm/memcontrol-v1.c index 4e4946728db5..8fa7b2fb109d 100644 --- a/mm/memcontrol-v1.c +++ b/mm/memcontrol-v1.c @@ -300,7 +300,9 @@ void __memcg1_swapout(struct folio *folio, struct swap_cluster_info *ci) */ nr_entries = folio_nr_pages(folio); private_id = mem_cgroup_private_id_get(memcg, nr_entries); - if (!is_vswap_entry(folio->swap)) + if (is_vswap_entry(folio->swap)) + mod_memcg_state(memcg, MEMCG_VSWAP, nr_entries); + else mod_memcg_state(memcg, MEMCG_SWAP, nr_entries); __swap_cgroup_set(ci, swp_cluster_offset(folio->swap), nr_entries, private_id); @@ -1842,6 +1844,7 @@ static const unsigned int memcg1_stats[] = { #ifdef CONFIG_SWAP MEMCG_SWAP, NR_SWAPCACHE, + MEMCG_VSWAP, #endif }; @@ -1860,6 +1863,7 @@ static const char *const memcg1_stat_names[] = { #ifdef CONFIG_SWAP "swap", "swapcached", + "vswap", #endif }; diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e2aa75a292ed..eedaa094a867 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -66,6 +66,7 @@ #include "internal.h" #include "swap.h" #include "swap_table.h" +#include "vswap.h" #include #include #include "slab.h" @@ -459,6 +460,7 @@ static const unsigned int memcg_stat_items[] = { MEMCG_ZSWAP_B, MEMCG_ZSWAPPED, MEMCG_ZSWAP_INCOMP, + MEMCG_VSWAP, }; #define NR_MEMCG_NODE_STAT_ITEMS ARRAY_SIZE(memcg_node_stat_items) @@ -1628,6 +1630,7 @@ static const struct memory_stat memory_stats[] = { { "file_writeback", NR_WRITEBACK }, #ifdef CONFIG_SWAP { "swapcached", NR_SWAPCACHE }, + { "vswap", MEMCG_VSWAP }, #endif #ifdef CONFIG_TRANSPARENT_HUGEPAGE { "anon_thp", NR_ANON_THPS }, @@ -6004,6 +6007,7 @@ unsigned short __mem_cgroup_swap_get(struct folio *folio) unsigned int nr_pages = folio_nr_pages(folio); struct mem_cgroup *memcg; struct obj_cgroup *objcg; + unsigned short id; if (do_memsw_account()) return 0; @@ -6020,7 +6024,12 @@ unsigned short __mem_cgroup_swap_get(struct folio *folio) return 0; } - return mem_cgroup_private_id_get(memcg, nr_pages); + id = mem_cgroup_private_id_get(memcg, nr_pages); + if (is_vswap_entry(folio->swap)) { + memcg = obj_cgroup_memcg(obj_cgroup_from_private_id(id)); + mod_memcg_state(memcg, MEMCG_VSWAP, nr_pages); + } + return id; } /** @@ -6109,7 +6118,7 @@ void __mem_cgroup_swap_uncharge(unsigned short id, unsigned int nr_pages) * __mem_cgroup_swap_put - drop the private ID refs taken for swap slots * @id: the pinned private ID * @nr_pages: number of refs to drop - * @is_vswap: whether the released swap slots are virtual + * @is_vswap: release virtual-swap accounting along with the refs */ void __mem_cgroup_swap_put(unsigned short id, unsigned int nr_pages, bool is_vswap) @@ -6117,9 +6126,12 @@ void __mem_cgroup_swap_put(unsigned short id, unsigned int nr_pages, struct mem_cgroup *memcg; guard(rcu)(); - if (do_memsw_account() && !is_vswap) { + if (is_vswap || do_memsw_account()) { memcg = obj_cgroup_memcg(obj_cgroup_from_private_id(id)); - mod_memcg_state(memcg, MEMCG_SWAP, -nr_pages); + if (is_vswap) + mod_memcg_state(memcg, MEMCG_VSWAP, -nr_pages); + else + mod_memcg_state(memcg, MEMCG_SWAP, -nr_pages); } mem_cgroup_private_id_put(id, nr_pages); } diff --git a/mm/swapfile.c b/mm/swapfile.c index e95f2441fdd7..fe5460d15f55 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2612,9 +2612,8 @@ static void __swap_cluster_free_phys_backing(struct swap_info_struct *psi, } /* - * Release the cgroup accounting of a batch of freed slots. For vswap the - * physical swap was already uncharged by __vswap_release_backing(), so only - * the ID ref is left to drop. + * Release cgroup accounting for freed swap slots. Physical backing of + * vswap entries was already uncharged by __vswap_release_backing(). */ static void memcg_swap_free(unsigned short id, unsigned int nr, bool is_vswap) { @@ -4922,6 +4921,11 @@ early_param("vswap", early_vswap); /* vswap does no IO on its own. */ static const struct swap_ops vswap_ops = { }; +unsigned long vswap_usage_in_pages(void) +{ + return vswap_is_enabled() ? swap_usage_in_pages(vswap_si) : 0; +} + static int vswap_used_get(void *data, u64 *val) { *val = swap_usage_in_pages(vswap_si); diff --git a/mm/vmstat.c b/mm/vmstat.c index a3e809c57f29..b7077a6f244d 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1320,6 +1320,9 @@ const char * const vmstat_text[] = { [I(NR_DIRTY_BG_THRESHOLD)] = "nr_dirty_background_threshold", [I(NR_MEMMAP_PAGES)] = "nr_memmap_pages", [I(NR_MEMMAP_BOOT_PAGES)] = "nr_memmap_boot_pages", +#ifdef CONFIG_SWAP + [I(NR_VSWAP)] = "nr_vswap", +#endif #undef I #if defined(CONFIG_VM_EVENT_COUNTERS) @@ -1936,6 +1939,9 @@ static void *vmstat_start(struct seq_file *m, loff_t *pos) v + NR_DIRTY_THRESHOLD); v[NR_MEMMAP_PAGES] = atomic_long_read(&nr_memmap_pages); v[NR_MEMMAP_BOOT_PAGES] = atomic_long_read(&nr_memmap_boot_pages); +#ifdef CONFIG_SWAP + v[NR_VSWAP] = vswap_usage_in_pages(); +#endif v += NR_VM_STAT_ITEMS; #ifdef CONFIG_VM_EVENT_COUNTERS -- 2.53.0-Meta