mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] mm/migrate: don't move memcg NR_FILE_PAGES for swapcache
@ 2026-11-04  4:43 Song Hu
  2026-11-04 15:54 ` Joshua Hahn
  0 siblings, 1 reply; 3+ messages in thread
From: Song Hu @ 2026-11-04  4:43 UTC (permalink / raw)
  To: akpm, david
  Cc: ziy, matthew.brost, joshua.hahnjy, byungchul, gourry, ying.huang,
	apopple, willy, shivankg, ridong.chen, linux-mm, linux-kernel,
	Song Hu

NR_FILE_PAGES lives on both the node and the memcg plane for page
cache folios: filemap_add_folio() and filemap_unaccount_folio() charge
it to the folio's node and memcg, while __swap_cache_add_folio() and
__swap_cache_del_folio() maintain the node plane of NR_FILE_PAGES and
the memcg plane of NR_SWAPCACHE.  A folio in the swap cache therefore
carries no per-memcg NR_FILE_PAGES count: shmem folios drop their
memcg file accounting when swapped out, and anon folios never had any.

The cross-zone arm of __folio_migrate_mapping() moves NR_FILE_PAGES on
both planes unconditionally.  For swapcache folios the memcg plane is
empty, so migrating one misaccounts it: the destination accrues
nr_pages that were never accounted there while the source counter
underflows.  The wrong counts persist until the memcg is destroyed,
but the aggregate in memory.stat stays correct, so the drift is easy
to miss.  NUMA balancing, migratepages, compaction and memory hotplug
can all migrate such folios.

Reproducer, on a 2-node QEMU guest with cgroup v2:

  1. create a cgroup with memory.max = 50M and swap enabled;
  2. memset 128M of anonymous memory in it, so reclaim swaps most of
     it out;
  3. fork to raise the swap entry refcount, then fault the memory
     back in, so the resident folios are swapcache ones;
  4. migrate_pages(pid, node0 -> node1).

"file" row of memory.numa_stat (bytes) after step 4:

                    without this patch      with this patch
                      N0          N1          N0          N1
                     0 (*)  51691520         0           0

  (*) the source counter has gone negative; negative values read as 0.

Keep moving the node plane via mod_node_page_state() and skip only
the empty memcg plane, mirroring the swapcache exclusion the NR_SHMEM
handling in the same block already applies.  It accompanies
commit 4eef27af2932 ("mm/migrate: move NR_FILE_THPS on cross-node migration")
and commit c5eef2e03618 ("mm/migrate: move NR_KERNEL_FILE_PAGES on cross-node migration").

Fixes: 0d1c20722ab3 ("mm: memcontrol: switch to native NR_FILE_PAGES and NR_SHMEM counters")
Signed-off-by: Song Hu <husong@kylinos.cn>
---
 mm/migrate.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/mm/migrate.c b/mm/migrate.c
index 28a8d7734735..bc60f6587d1b 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -690,8 +690,20 @@ static int __folio_migrate_mapping(struct address_space *mapping,
 		old_lruvec = mem_cgroup_lruvec(memcg, oldzone->zone_pgdat);
 		new_lruvec = mem_cgroup_lruvec(memcg, newzone->zone_pgdat);
 
-		mod_lruvec_state(old_lruvec, NR_FILE_PAGES, -nr);
-		mod_lruvec_state(new_lruvec, NR_FILE_PAGES, nr);
+		/*
+		 * Swapcache folios carry NR_FILE_PAGES on the node plane
+		 * only (their memcg footprint is NR_SWAPCACHE, see
+		 * swap_state.c), so move only the node plane for them.
+		 */
+		if (folio_test_swapcache(folio)) {
+			mod_node_page_state(oldzone->zone_pgdat, NR_FILE_PAGES,
+					    -nr);
+			mod_node_page_state(newzone->zone_pgdat, NR_FILE_PAGES,
+					    nr);
+		} else {
+			mod_lruvec_state(old_lruvec, NR_FILE_PAGES, -nr);
+			mod_lruvec_state(new_lruvec, NR_FILE_PAGES, nr);
+		}
 		if (folio_test_swapbacked(folio) && !folio_test_swapcache(folio)) {
 			mod_lruvec_state(old_lruvec, NR_SHMEM, -nr);
 			mod_lruvec_state(new_lruvec, NR_SHMEM, nr);
-- 
2.53.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-11-05 10:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04  4:43 [PATCH] mm/migrate: don't move memcg NR_FILE_PAGES for swapcache Song Hu
2026-11-04 15:54 ` Joshua Hahn
2026-11-05 10:10   ` David Hildenbrand (Arm)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®