From: Zi Yan <z...@nvidia.com>

We cannot swap 1GB THPs, so split them before swap them out.

Signed-off-by: Zi Yan <z...@nvidia.com>
---
 mm/swap_slots.c |  2 ++
 mm/vmscan.c     | 55 ++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/mm/swap_slots.c b/mm/swap_slots.c
index 63a7b4563a57..797c804ff905 100644
--- a/mm/swap_slots.c
+++ b/mm/swap_slots.c
@@ -315,6 +315,8 @@ swp_entry_t get_swap_page(struct page *page)
        entry.val = 0;
 
        if (PageTransHuge(page)) {
+               if (compound_order(page) == HPAGE_PUD_ORDER)
+                       return entry;
                if (IS_ENABLED(CONFIG_THP_SWAP))
                        get_swap_pages(1, &entry, HPAGE_PMD_NR);
                goto out;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index a714c4f800e9..a2a91c1d3dae 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1288,25 +1288,47 @@ static unsigned long shrink_page_list(struct list_head 
*page_list,
                                if (!(sc->gfp_mask & __GFP_IO))
                                        goto keep_locked;
                                if (PageTransHuge(page)) {
-                                       /* cannot split THP, skip it */
-                                       if (!can_split_huge_page(page, NULL))
-                                               goto activate_locked;
-                                       /*
-                                        * Split pages without a PMD map right
-                                        * away. Chances are some or all of the
-                                        * tail pages can be freed without IO.
-                                        */
-                                       if (!compound_mapcount(page) &&
-                                           split_huge_page_to_list(page,
-                                                                   page_list))
+                                       if (compound_order(page) == 
HPAGE_PUD_ORDER) {
+                                               /* cannot split THP, skip it */
+                                               if 
(!can_split_huge_pud_page(page, NULL))
+                                                       goto activate_locked;
+                                               /*
+                                                * Split pages without a PMD 
map right
+                                                * away. Chances are some or 
all of the
+                                                * tail pages can be freed 
without IO.
+                                                */
+                                               if (!compound_mapcount(page) &&
+                                                       
split_huge_pud_page_to_list(page,
+                                                                               
page_list))
+                                                       goto activate_locked;
+                                       }
+                                       if (compound_order(page) == 
HPAGE_PMD_ORDER) {
+                                               /* cannot split THP, skip it */
+                                               if (!can_split_huge_page(page, 
NULL))
+                                                       goto activate_locked;
+                                               /*
+                                                * Split pages without a PMD 
map right
+                                                * away. Chances are some or 
all of the
+                                                * tail pages can be freed 
without IO.
+                                                */
+                                               if (!compound_mapcount(page) &&
+                                                       
split_huge_page_to_list(page,
+                                                                               
page_list))
+                                                       goto activate_locked;
+                                       }
+                               }
+                               if (compound_order(page) == HPAGE_PUD_ORDER) {
+                                       if (split_huge_pud_page_to_list(page,
+                                                                       
page_list))
                                                goto activate_locked;
                                }
                                if (!add_to_swap(page)) {
                                        if (!PageTransHuge(page))
                                                goto activate_locked;
                                        /* Fallback to swap normal pages */
+                                       VM_BUG_ON_PAGE(compound_order(page) != 
HPAGE_PMD_ORDER, page);
                                        if (split_huge_page_to_list(page,
-                                                                   page_list))
+                                                                       
page_list))
                                                goto activate_locked;
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
                                        count_vm_event(THP_SWPOUT_FALLBACK);
@@ -1321,6 +1343,7 @@ static unsigned long shrink_page_list(struct list_head 
*page_list,
                                mapping = page_mapping(page);
                        }
                } else if (unlikely(PageTransHuge(page))) {
+                       VM_BUG_ON_PAGE(compound_order(page) != HPAGE_PMD_ORDER, 
page);
                        /* Split file THP */
                        if (split_huge_page_to_list(page, page_list))
                                goto keep_locked;
@@ -1333,8 +1356,12 @@ static unsigned long shrink_page_list(struct list_head 
*page_list,
                if (page_mapped(page)) {
                        enum ttu_flags flags = ttu_flags | TTU_BATCH_FLUSH;
 
-                       if (unlikely(PageTransHuge(page)))
-                               flags |= TTU_SPLIT_HUGE_PMD;
+                       if (unlikely(PageTransHuge(page))) {
+                               if (compound_order(page) == HPAGE_PMD_ORDER)
+                                       flags |= TTU_SPLIT_HUGE_PMD;
+                               else if (compound_order(page) == 
HPAGE_PUD_ORDER)
+                                       flags |= TTU_SPLIT_HUGE_PUD;
+                       }
                        if (!try_to_unmap(page, flags)) {
                                nr_unmap_fail++;
                                goto activate_locked;
-- 
2.20.1

Reply via email to