[Devel] [PATCH VZ9 2/2] mm: migrate page private for high-order folios in swap cache correctly

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Wed Mar 6 11:36:04 MSK 2024


We have a check in do_swap_page that page from lookup_swap_cache should
have private field equal to the swapcache index we searched it at
(page_private(page) != entry.val). So folio_migrate_mapping should
preserve page private for each page of a huge folio to satisfy this
check else we get infinite loop in:

  +-> mmap_read_lock
  +-> __get_user_pages_locked
    +-> for-loop # taken once
      +-> __get_user_pages
        +-> retry-loop # constantly spinning
          +-> faultin_page # return 0 to trigger retry
            +-> handle_mm_fault
              +-> __handle_mm_fault
                +-> handle_pte_fault
                  +-> do_swap_page
                    +-> lookup_swap_cache # returns non-NULL
                    +-> if (swapcache)
                      +-> if (!folio_test_swapcache || page_private(page) != entry.val)
                        +-> goto out_page
                          +-> return 0

And this loop is under mmap_lock so we have secondary problem of
multiple processes hanging on attempt to take mmap_lock.

Note: We don't need this after we stop using private in this ms patch:
cfeed8ffe55b ("mm/swap: stop using page->private on tail pages for THP_SWAP")

https://virtuozzo.atlassian.net/browse/PSBM-153264
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 mm/migrate.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/mm/migrate.c b/mm/migrate.c
index d950f42c0708..357a0a4c59e6 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -424,6 +424,10 @@ int folio_migrate_mapping(struct address_space *mapping,
 		if (folio_test_swapcache(folio)) {
 			folio_set_swapcache(newfolio);
 			newfolio->private = folio_get_private(folio);
+
+			/* Swap cache needs private for each page of huge page */
+			for (i = 1; i < nr; i++)
+				set_page_private(folio_page(newfolio, i), folio_page(folio, i)->private);
 		}
 		entries = nr;
 	} else {
-- 
2.43.0



More information about the Devel mailing list