Re: [PATCH v5 14/19] mm, swap: cleanup swap entry management workflow

From: Kairui Song

Date: Wed Jan 14 2026 - 11:54:20 EST


On Sat, Dec 20, 2025 at 3:45 AM Kairui Song <ryncsn@xxxxxxxxx> wrote:
>
> From: Kairui Song <kasong@xxxxxxxxxxx>
>
> The current swap entry allocation/freeing workflow has never had a clear
> definition. This makes it hard to debug or add new optimizations.
>
> This commit introduces a proper definition of how swap entries would be
> allocated and freed. Now, most operations are folio based, so they will
> never exceed one swap cluster, and we now have a cleaner border between
> swap and the rest of mm, making it much easier to follow and debug,
> especially with new added sanity checks. Also making more optimization
> possible.

...

>
> Cc: linux-pm@xxxxxxxxxxxxxxx
> Acked-by: Rafael J. Wysocki (Intel) <rafael@xxxxxxxxxx>
> Signed-off-by: Kairui Song <kasong@xxxxxxxxxxx>
> ---

Hi Andrew,

Is it convenient for you to squash this attached fix into this patch?
That's the two issues from Chris Mason and Lai Yi combined in a clean
to apply format, only 3 lines change.

There might be minor conflict by removing the WARN_ON in two following
patches, but should be easy to resolve. I can send a v6 if that's
troublesome.
From 1f34d6dbe378d9fe2f45445fc791275aaedb8482 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@tencent.com>
Date: Thu, 15 Jan 2026 00:15:27 +0800
Subject: [PATCH] mm, swap: fix locking and leaking with hibernation snapshot
releasing

Chris Mason reported that there is a leak with hibernation, and Lai Yi
also noticed the new added WARN_ON is not helpful but causing issue, so
patch both issues.

Signed-off-by: Kairui Song <kasong@tencent.com>
---
kernel/power/swap.c | 2 +-
mm/swapfile.c | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 036489d3b01a..19ed7bd2adcc 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -199,7 +199,7 @@ void free_all_swap_pages(int swap)
ext = rb_entry(node, struct swsusp_extent, node);
rb_erase(node, &swsusp_extents);

- for (offset = ext->start; offset < ext->end; offset++)
+ for (offset = ext->start; offset <= ext->end; offset++)
swap_free_hibernation_slot(swp_entry(swap, offset));

kfree(ext);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 85bf4f7d9ae7..8c0f31363c1f 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2096,7 +2096,6 @@ void swap_free_hibernation_slot(swp_entry_t entry)

ci = swap_cluster_lock(si, offset);
swap_entry_put_locked(si, ci, entry, 1);
- WARN_ON(swap_entry_swapped(si, entry));
swap_cluster_unlock(ci);

/* In theory readahead might add it to the swap cache by accident */
--
2.52.0