diff --git a/include/linux/swap_cgroup.h b/include/linux/swap_cgroup.h index 91cdf12190a0..fd79e7bf8917 100644 --- a/include/linux/swap_cgroup.h +++ b/include/linux/swap_cgroup.h @@ -7,6 +7,7 @@ #if defined(CONFIG_MEMCG) && defined(CONFIG_SWAP) extern void swap_cgroup_record(struct folio *folio, unsigned short id, swp_entry_t ent); +extern unsigned short swap_cgroup_lookup(swp_entry_t ent); extern unsigned short swap_cgroup_clear(swp_entry_t ent, unsigned int nr_ents); extern unsigned short lookup_swap_cgroup_id(swp_entry_t ent); extern int swap_cgroup_swapon(int type, unsigned long max_pages); @@ -19,6 +20,11 @@ void swap_cgroup_record(struct folio *folio, unsigned short id, swp_entry_t ent) { } +static inline unsigned short swap_cgroup_lookup(swp_entry_t ent) +{ + return 0; +} + static inline unsigned short swap_cgroup_clear(swp_entry_t ent, unsigned int nr_ents) { diff --git a/mm/memcontrol-v1.c b/mm/memcontrol-v1.c index 56d27baf93ab..37899d156b2a 100644 --- a/mm/memcontrol-v1.c +++ b/mm/memcontrol-v1.c @@ -614,6 +614,7 @@ void memcg1_swapout(struct folio *folio, swp_entry_t entry) { struct mem_cgroup *memcg, *swap_memcg; unsigned int nr_entries; + unsigned short oldid; VM_BUG_ON_FOLIO(folio_test_lru(folio), folio); VM_BUG_ON_FOLIO(folio_ref_count(folio), folio); @@ -630,6 +631,12 @@ void memcg1_swapout(struct folio *folio, swp_entry_t entry) if (!memcg) return; + oldid = swap_cgroup_lookup(entry); + if (oldid == mem_cgroup_id(memcg)) { + return; + } + VM_WARN_ON_ONCE(oldid != 0); + /* * In case the memcg owning these pages has been offlined and doesn't * have an ID allocated to it anymore, charge the closest online diff --git a/mm/swap_cgroup.c b/mm/swap_cgroup.c index de779fed8c21..083eda4b67d6 100644 --- a/mm/swap_cgroup.c +++ b/mm/swap_cgroup.c @@ -51,6 +51,24 @@ static unsigned short __swap_cgroup_id_xchg(struct swap_cgroup *map, return old_id; } +unsigned short swap_cgroup_lookup(swp_entry_t ent) +{ + struct swap_cgroup *sc; + unsigned short id; + pgoff_t offset = swp_offset(ent); + unsigned short type = swp_type(ent); + + if (type >= MAX_SWAPFILES) + return 0; + + sc = swap_cgroup_ctrl[type].map; + if (!sc) + return 0; + id = (unsigned short)atomic_read(&sc[offset].ids); + return id; + +} + /** * swap_cgroup_record - record mem_cgroup for a set of swap entries. * These entries must belong to one single folio, and that folio