[Devel] [PATCH RHEL7 COMMIT] mm/tswap: make tswap_delete_page handle replaced page gracefully

Konstantin Khorenko khorenko at virtuozzo.com
Tue Apr 26 16:36:56 MSK 2022


The commit is pushed to "branch-rh7-3.10.0-1160.59.1.vz7.186.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.59.1.vz7.186.2
------>
commit 16d1499c3c62982b837429a11c5aa7be5e17a474
Author: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
Date:   Tue Apr 26 11:40:59 2022 +0300

    mm/tswap: make tswap_delete_page handle replaced page gracefully
    
    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 | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/mm/tswap.c b/mm/tswap.c
index e209654fcb4b..07d92a0c86cc 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);


More information about the Devel mailing list