[Devel] [PATCH RH7] mm/tswap: make tswap_delete_page handle replaced page gracefully
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Tue Apr 26 11:40:59 MSK 2022
When we want to delete specific page from the frontswap, and it was
replaced with another page between lookup and delete while tswap_lock
had been released, just consider removal successful.
This potential call stack could've lead to the crash on BUG_ON:
THREAD 1
tswap_shrink_scan () {
spin_lock(&tswap_lock);
page = list_first_entry(&lru->list, struct page, lru); # gets page-1
trylock_page(page); # locked page-1 succesfully
get_page(page);
spin_unlock(&tswap_lock);
THREAD 2
tswap_frontswap_store(page) { # store page-2 with same swap entry
cache_page = tswap_lookup_page(entry); # gets page-1
tswap_delete_page(entry, NULL); # locks/unlocks tswap_lock, removes page-1
tswap_insert_page(entry, cache_page); # locks/unlocks tswap_lock, inserts page-2
}
tswap_evict_page(page) {
tswap_delete_page(entry, page) {
spin_lock(&tswap_lock);
page = radix_tree_delete_item(&tswap_page_tree); # gets page-2
spin_unlock(&tswap_lock);
BUG_ON(expected && page != expected); # expected is page-1, but page is page-2
}
}
}
https://jira.sw.ru/browse/PSBM-139322
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
mm/tswap.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/mm/tswap.c b/mm/tswap.c
index e209654fcb4b..e4aa2854ede3 100644
--- a/mm/tswap.c
+++ b/mm/tswap.c
@@ -116,6 +116,13 @@ static struct page *tswap_delete_page(swp_entry_t entry, struct page *expected)
struct page *page;
spin_lock(&tswap_lock);
+ if (expected) {
+ page = radix_tree_lookup(&tswap_page_tree, entry.val);
+ if (page && page != expected) {
+ spin_unlock(&tswap_lock);
+ return expected;
+ }
+ }
page = radix_tree_delete_item(&tswap_page_tree, entry.val, expected);
if (page) {
tswap_lru_del(page);
@@ -328,7 +335,7 @@ static int tswap_frontswap_store(unsigned type, pgoff_t offset,
/* If type of page has not changed, just reuse it */
if (zero_filled == (cache_page == ZERO_PAGE(0)))
goto copy;
- tswap_delete_page(entry, NULL);
+ tswap_delete_page(entry, cache_page);
put_page(cache_page);
}
--
2.35.1
More information about the Devel
mailing list