[PATCH] mm: Free unused swap cache page in write protection fault handler

From: Huang Ying
Date: Tue Jan 12 2021 - 21:44:25 EST


Commit 09854ba94c6a ("mm: do_wp_page() simplification") introduces an
issue as follows.

On a system with free memory as follow before test,

total used free shared buff/cache available
Mem: 1697300 160156 1459220 8648 77924 1419724
Swap: 1048572 0 0

The AnonPages filed of /proc/meminfo is 11712 kB. After running a
memory eater which will trigger many swapins and write protection
faults, the free memory becomes,

total used free shared buff/cache available
Mem: 1697300 352620 1309004 624 35676 1252380
Swap: 1048572 216924 831648

While the /proc/meminfo shows,

SwapCached: 198908 kB
AnonPages: 1956 kB

Then, with `swapoff -a`, the free memory becomes,

total used free shared buff/cache available
Mem: 1697300 161972 1488184 8648 47144 1433172
Swap: 0 0 0

That is, after swapins and write protection faults, many unused swap
cache pages will be left unfreed in system. Although the following
page reclaiming or swapoff will free these pages, it's still better to
free these pages at the first place.

So in this patch, at the end of wp_page_copy(), the old unused swap
cache page will be tried to be freed. With that, after running the
memory eater which will trigger many swapins and write protection
faults, the free memory is,

total used free shared buff/cache available
Mem: 1697300 154020 1509400 1212 33880 1451524
Swap: 1048572 18432 1030140

While the /proc/meminfo shows,

SwapCached: 1240 kB
AnonPages: 1904 kB

BTW: I think this should be in stable after v5.9.

Fixes: 09854ba94c6a ("mm: do_wp_page() simplification")
Signed-off-by: "Huang, Ying" <ying.huang@xxxxxxxxx>
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Cc: Peter Xu <peterx@xxxxxxxxxx>
Cc: Hugh Dickins <hughd@xxxxxxxxxx>
Cc: Johannes Weiner <hannes@xxxxxxxxxxx>
Cc: Mel Gorman <mgorman@xxxxxxx>
Cc: Rik van Riel <riel@xxxxxxxxxxx>
Cc: Andrea Arcangeli <aarcange@xxxxxxxxxx>
Cc: Michal Hocko <mhocko@xxxxxxxxxx>
Cc: Dave Hansen <dave.hansen@xxxxxxxxx>
Cc: Tim Chen <tim.c.chen@xxxxxxxxx>
---
mm/memory.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/mm/memory.c b/mm/memory.c
index feff48e1465a..2abaff1befcb 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2963,6 +2963,11 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
munlock_vma_page(old_page);
unlock_page(old_page);
}
+ if (page_copied && PageSwapCache(old_page) &&
+ !page_mapped(old_page) && trylock_page(old_page)) {
+ try_to_free_swap(old_page);
+ unlock_page(old_page);
+ }
put_page(old_page);
}
return page_copied ? VM_FAULT_WRITE : 0;
--
2.29.2