diff options
Diffstat (limited to 'mm/migrate.c')
-rw-r--r-- | mm/migrate.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index 690d0de993af..1a531b760b3b 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -113,6 +113,8 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma, | |||
113 | goto out; | 113 | goto out; |
114 | 114 | ||
115 | pmd = pmd_offset(pud, addr); | 115 | pmd = pmd_offset(pud, addr); |
116 | if (pmd_trans_huge(*pmd)) | ||
117 | goto out; | ||
116 | if (!pmd_present(*pmd)) | 118 | if (!pmd_present(*pmd)) |
117 | goto out; | 119 | goto out; |
118 | 120 | ||
@@ -632,6 +634,9 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
632 | /* page was freed from under us. So we are done. */ | 634 | /* page was freed from under us. So we are done. */ |
633 | goto move_newpage; | 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 | /* prepare cgroup just returns 0 or -ENOMEM */ | 641 | /* prepare cgroup just returns 0 or -ENOMEM */ |
637 | rc = -EAGAIN; | 642 | rc = -EAGAIN; |
@@ -1063,7 +1068,7 @@ static int do_move_page_to_node_array(struct mm_struct *mm, | |||
1063 | if (!vma || pp->addr < vma->vm_start || !vma_migratable(vma)) | 1068 | if (!vma || pp->addr < vma->vm_start || !vma_migratable(vma)) |
1064 | goto set_status; | 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 | err = PTR_ERR(page); | 1073 | err = PTR_ERR(page); |
1069 | if (IS_ERR(page)) | 1074 | if (IS_ERR(page)) |