2023-06-27 12:23:53

by mawupeng

[permalink] [raw]
Subject: [PATCH 2/2] swap: Stop add to avail list is swap is full

From: Ma Wupeng <[email protected]>

Our test find a WARN_ON in add_to_avail_list. During add_to_avail_list,
avail_lists is already in swap_avail_heads, while lead to this WARN_ON.

Here is the simplified calltrace:

------------[ cut here ]------------
Call trace:
add_to_avail_list+0xb8/0xc0
swap_range_free+0x110/0x138
swapcache_free_entries+0x100/0x1c0
free_swap_slot+0xbc/0xe0
put_swap_folio+0x1f0/0x2ec
delete_from_swap_cache+0x6c/0xd0
folio_free_swap+0xa4/0xe4
__try_to_reclaim_swap+0x9c/0x190
free_swap_and_cache+0x84/0x88
unmap_page_range+0x31c/0x934
unmap_single_vma.isra.0+0x48/0x84
unmap_vmas+0x98/0x10c
exit_mmap+0xa4/0x210
mmput+0x88/0x158
do_exit+0x284/0x970
do_group_exit+0x34/0x90
post_copy_siginfo_from_user32+0x0/0x1cc
do_notify_resume+0x15c/0x470
el0_svc+0x74/0x84
el0t_64_sync_handler+0xb8/0xbc
el0t_64_sync+0x190/0x194

During swapoff, try_to_unuse fail to alloc memory due to memory limit and
this lead the failure of swapoff and casing re-insert swap space back into
swap_list. During _enable_swap_info, this swap device is added to avail
list even this swap device if full. At the same time, one entry in this
full swap device in released and try to add this device into avail list
and found it is already in the avail list. This cause this WARN_ON.

To fix this. Stop add to avail list is swap is full.

Signed-off-by: Ma Wupeng <[email protected]>
---
mm/swapfile.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 879cb80bf37b..0167999fa228 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2337,7 +2337,10 @@ static void _enable_swap_info(struct swap_info_struct *p)
* swap_info_struct.
*/
plist_add(&p->list, &swap_active_head);
- add_to_avail_list(p);
+
+ /* add to avaliable list iff swap device is not full */
+ if (p->highest_bit)
+ add_to_avail_list(p);
}

static void enable_swap_info(struct swap_info_struct *p, int prio,
--
2.25.1