[Devel] [PATCH vz9] mm/memcontrol: fix cache counter imbalance in mem_cgroup_replace_folio()
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Thu Jul 24 07:10:00 MSK 2025
On 7/24/25 00:31, Konstantin Khorenko wrote:
> The function was checking cache flag on the new folio instead of the old one,
> causing cache counter imbalance when replacing cache pages.
> The new folio is freshly allocated and never has the cache flag set, so
> we need to copy the flag from the old folio and charge the cache counter
> accordingly.
>
> This fixes potential cache accounting issues during page cache replacement
> operations like page migration between NUMA nodes.
>
> Fixes: 763a087e29d11 ("mm: Memory cgroup page cache limit")
> https://virtuozzo.atlassian.net/browse/VSTOR-111756
>
> Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
>
> Feature: mm: Memory cgroup page cache limit
> ---
> mm/memcontrol.c | 9 ++++++---
> 1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index cefb72234fda5..af70959f00c8e 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -8292,6 +8292,12 @@ void mem_cgroup_migrate(struct folio *old, struct folio *new)
> page_counter_charge(&memcg->memsw, nr_pages);
> }
>
> + if (folio_memcg_cache(old)) {
> + WRITE_ONCE(folio->memcg_data,
We don't seem to have "folio" variable here on vz9 (at least I checked
in rh9-5.14.0-427.77.1.vz9.86.2), probably meant to be "new".
> + READ_ONCE(folio->memcg_data) | MEMCG_DATA_PGCACHE);
> + page_counter_charge(&memcg->cache, nr_pages);
> + }
> +
> /*
> * finist explained the idea behind adding a WARN_ON() here:
> * - we do not want to check flags correctness on each flag change
> @@ -8312,9 +8318,6 @@ void mem_cgroup_migrate(struct folio *old, struct folio *new)
> folio_test_swapbacked(new) || folio_test_swapcache(new) ||
> folio_test_mappedtodisk(new) || folio_test_ksm(new)));
>
> - if (folio_memcg_cache(new))
> - page_counter_charge(&memcg->cache, nr_pages);
> -
> css_get(&memcg->css);
> commit_charge(new, memcg);
This commit_charge is probably making all our efforts vain, as it resets
flags in new->memcg_data by putting memory cgroup pointer there. E.g. in
charge_memcg we first do commit_charge and only then add our flag to it.
I believe we must put WRITE_ONCE after commit_charge, same for our
"WARN_ON(folio_memcg_cache(new)...".
>
--
Best regards, Pavel Tikhomirov
Senior Software Developer, Virtuozzo.
More information about the Devel
mailing list