Skip to content

Commit 85ce2c5

Browse files
nhatsmrtakpm00
authored andcommitted
memcontrol: only transfer the memcg data for migration
For most migration use cases, only transfer the memcg data from the old folio to the new folio, and clear the old folio's memcg data. No charging and uncharging will be done. This shaves off some work on the migration path, and avoids the temporary double charging of a folio during its migration. The only exception is replace_page_cache_folio(), which will use the old mem_cgroup_migrate() (now renamed to mem_cgroup_replace_folio). In that context, the isolation of the old page isn't quite as thorough as with migration, so we cannot use our new implementation directly. This patch is the result of the following discussion on the new hugetlb memcg accounting behavior: https://lore.kernel.org/lkml/20231003171329.GB314430@monkey/ Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Nhat Pham <[email protected]> Suggested-by: Johannes Weiner <[email protected]> Acked-by: Johannes Weiner <[email protected]> Cc: Frank van der Linden <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Mike Kravetz <[email protected]> Cc: Muchun Song <[email protected]> Cc: Rik van Riel <[email protected]> Cc: Roman Gushchin <[email protected]> Cc: Shakeel Butt <[email protected]> Cc: Shuah Khan <[email protected]> Cc: Tejun heo <[email protected]> Cc: Yosry Ahmed <[email protected]> Cc: Zefan Li <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 4b56938 commit 85ce2c5

File tree

3 files changed

+45
-4
lines changed

3 files changed

+45
-4
lines changed

include/linux/memcontrol.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,8 @@ static inline void mem_cgroup_uncharge_list(struct list_head *page_list)
707707

708708
void mem_cgroup_cancel_charge(struct mem_cgroup *memcg, unsigned int nr_pages);
709709

710+
void mem_cgroup_replace_folio(struct folio *old, struct folio *new);
711+
710712
void mem_cgroup_migrate(struct folio *old, struct folio *new);
711713

712714
/**
@@ -1279,6 +1281,11 @@ static inline void mem_cgroup_cancel_charge(struct mem_cgroup *memcg,
12791281
{
12801282
}
12811283

1284+
static inline void mem_cgroup_replace_folio(struct folio *old,
1285+
struct folio *new)
1286+
{
1287+
}
1288+
12821289
static inline void mem_cgroup_migrate(struct folio *old, struct folio *new)
12831290
{
12841291
}

mm/filemap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ void replace_page_cache_folio(struct folio *old, struct folio *new)
816816
new->mapping = mapping;
817817
new->index = offset;
818818

819-
mem_cgroup_migrate(old, new);
819+
mem_cgroup_replace_folio(old, new);
820820

821821
xas_lock_irq(&xas);
822822
xas_store(&xas, new);

mm/memcontrol.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7292,16 +7292,17 @@ void __mem_cgroup_uncharge_list(struct list_head *page_list)
72927292
}
72937293

72947294
/**
7295-
* mem_cgroup_migrate - Charge a folio's replacement.
7295+
* mem_cgroup_replace_folio - Charge a folio's replacement.
72967296
* @old: Currently circulating folio.
72977297
* @new: Replacement folio.
72987298
*
72997299
* Charge @new as a replacement folio for @old. @old will
7300-
* be uncharged upon free.
7300+
* be uncharged upon free. This is only used by the page cache
7301+
* (in replace_page_cache_folio()).
73017302
*
73027303
* Both folios must be locked, @new->mapping must be set up.
73037304
*/
7304-
void mem_cgroup_migrate(struct folio *old, struct folio *new)
7305+
void mem_cgroup_replace_folio(struct folio *old, struct folio *new)
73057306
{
73067307
struct mem_cgroup *memcg;
73077308
long nr_pages = folio_nr_pages(new);
@@ -7340,6 +7341,39 @@ void mem_cgroup_migrate(struct folio *old, struct folio *new)
73407341
local_irq_restore(flags);
73417342
}
73427343

7344+
/**
7345+
* mem_cgroup_migrate - Transfer the memcg data from the old to the new folio.
7346+
* @old: Currently circulating folio.
7347+
* @new: Replacement folio.
7348+
*
7349+
* Transfer the memcg data from the old folio to the new folio for migration.
7350+
* The old folio's data info will be cleared. Note that the memory counters
7351+
* will remain unchanged throughout the process.
7352+
*
7353+
* Both folios must be locked, @new->mapping must be set up.
7354+
*/
7355+
void mem_cgroup_migrate(struct folio *old, struct folio *new)
7356+
{
7357+
struct mem_cgroup *memcg;
7358+
7359+
VM_BUG_ON_FOLIO(!folio_test_locked(old), old);
7360+
VM_BUG_ON_FOLIO(!folio_test_locked(new), new);
7361+
VM_BUG_ON_FOLIO(folio_test_anon(old) != folio_test_anon(new), new);
7362+
VM_BUG_ON_FOLIO(folio_nr_pages(old) != folio_nr_pages(new), new);
7363+
7364+
if (mem_cgroup_disabled())
7365+
return;
7366+
7367+
memcg = folio_memcg(old);
7368+
VM_WARN_ON_ONCE_FOLIO(!memcg, old);
7369+
if (!memcg)
7370+
return;
7371+
7372+
/* Transfer the charge and the css ref */
7373+
commit_charge(new, memcg);
7374+
old->memcg_data = 0;
7375+
}
7376+
73437377
DEFINE_STATIC_KEY_FALSE(memcg_sockets_enabled_key);
73447378
EXPORT_SYMBOL(memcg_sockets_enabled_key);
73457379

0 commit comments

Comments
 (0)