[PATCH RFC 09/15] mm, swap: support flexible batch freeing of slots in different memcg
From: Kairui Song via B4 Relay
Date: Thu Feb 19 2026 - 18:46:17 EST
From: Kairui Song <kasong@xxxxxxxxxxx>
Instead of let the caller ensures all slots are in the same memcg, the
make it be able to handle different memcg at once.
Signed-off-by: Kairui Song <kasong@xxxxxxxxxxx>
---
mm/swapfile.c | 31 +++++++++++++++++++++++++------
1 file changed, 25 insertions(+), 6 deletions(-)
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 2cd3e260f1bf..cd2d3b2ca6f0 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1883,10 +1883,13 @@ void __swap_cluster_free_entries(struct swap_info_struct *si,
struct swap_cluster_info *ci,
unsigned int ci_start, unsigned int nr_pages)
{
+ void *shadow;
unsigned long old_tb;
- unsigned short id;
+ unsigned int type = si->type;
+ unsigned int id = 0, id_iter, id_check;
unsigned int ci_off = ci_start, ci_end = ci_start + nr_pages;
- unsigned long offset = cluster_offset(si, ci) + ci_start;
+ unsigned long offset = cluster_offset(si, ci);
+ unsigned int ci_batch = ci_off;
VM_WARN_ON(ci->count < nr_pages);
@@ -1896,13 +1899,29 @@ void __swap_cluster_free_entries(struct swap_info_struct *si,
/* Release the last ref, or after swap cache is dropped */
VM_WARN_ON(!swp_tb_is_shadow(old_tb) || __swp_tb_get_count(old_tb) > 1);
__swap_table_set(ci, ci_off, null_to_swp_tb());
+
+ shadow = swp_tb_to_shadow(old_tb);
+ id_iter = shadow_to_memcgid(shadow);
+ if (id != id_iter) {
+ if (id) {
+ id_check = swap_cgroup_clear(swp_entry(type, offset + ci_batch),
+ ci_off - ci_batch);
+ WARN_ON(id != id_check);
+ mem_cgroup_uncharge_swap(id, ci_off - ci_batch);
+ }
+ id = id_iter;
+ ci_batch = ci_off;
+ }
} while (++ci_off < ci_end);
- id = swap_cgroup_clear(swp_entry(si->type, offset), nr_pages);
- if (id)
- mem_cgroup_uncharge_swap(id, nr_pages);
+ if (id) {
+ id_check = swap_cgroup_clear(swp_entry(type, offset + ci_batch),
+ ci_off - ci_batch);
+ WARN_ON(id != id_check);
+ mem_cgroup_uncharge_swap(id, ci_off - ci_batch);
+ }
- swap_range_free(si, offset, nr_pages);
+ swap_range_free(si, offset + ci_start, nr_pages);
swap_cluster_assert_empty(ci, ci_start, nr_pages, false);
if (!ci->count)
--
2.53.0