Commit 500d65d471018d9a13b0d51b7e141ed2a3555c1d

Authored by Andrea Arcangeli
Committed by Linus Torvalds
1 parent 0af4e98b6b

thp: pmd_trans_huge migrate bugcheck

No pmd_trans_huge should ever materialize in migration ptes areas, because
we split the hugepage before migration ptes are instantiated.

Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Acked-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 12 additions and 1 deletions Side-by-side Diff

... ... @@ -1490,6 +1490,7 @@
1490 1490 #define FOLL_DUMP 0x08 /* give error on hole if it would be zero */
1491 1491 #define FOLL_FORCE 0x10 /* get_user_pages read/write w/o permission */
1492 1492 #define FOLL_MLOCK 0x40 /* mark page as mlocked */
  1493 +#define FOLL_SPLIT 0x80 /* don't return transhuge pages, split them */
1493 1494  
1494 1495 typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
1495 1496 void *data);
... ... @@ -1305,6 +1305,10 @@
1305 1305 goto out;
1306 1306 }
1307 1307 if (pmd_trans_huge(*pmd)) {
  1308 + if (flags & FOLL_SPLIT) {
  1309 + split_huge_page_pmd(mm, pmd);
  1310 + goto split_fallthrough;
  1311 + }
1308 1312 spin_lock(&mm->page_table_lock);
1309 1313 if (likely(pmd_trans_huge(*pmd))) {
1310 1314 if (unlikely(pmd_trans_splitting(*pmd))) {
... ... @@ -1320,6 +1324,7 @@
1320 1324 spin_unlock(&mm->page_table_lock);
1321 1325 /* fall through */
1322 1326 }
  1327 +split_fallthrough:
1323 1328 if (unlikely(pmd_bad(*pmd)))
1324 1329 goto no_page_table;
1325 1330  
... ... @@ -113,6 +113,8 @@
113 113 goto out;
114 114  
115 115 pmd = pmd_offset(pud, addr);
  116 + if (pmd_trans_huge(*pmd))
  117 + goto out;
116 118 if (!pmd_present(*pmd))
117 119 goto out;
118 120  
... ... @@ -632,6 +634,9 @@
632 634 /* page was freed from under us. So we are done. */
633 635 goto move_newpage;
634 636 }
  637 + if (unlikely(PageTransHuge(page)))
  638 + if (unlikely(split_huge_page(page)))
  639 + goto move_newpage;
635 640  
636 641 /* prepare cgroup just returns 0 or -ENOMEM */
637 642 rc = -EAGAIN;
... ... @@ -1063,7 +1068,7 @@
1063 1068 if (!vma || pp->addr < vma->vm_start || !vma_migratable(vma))
1064 1069 goto set_status;
1065 1070  
1066   - page = follow_page(vma, pp->addr, FOLL_GET);
  1071 + page = follow_page(vma, pp->addr, FOLL_GET|FOLL_SPLIT);
1067 1072  
1068 1073 err = PTR_ERR(page);
1069 1074 if (IS_ERR(page))