diff options
Diffstat (limited to 'mm/migrate.c')
-rw-r--r-- | mm/migrate.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index 482a33d89134..bed48809e5d0 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -178,6 +178,37 @@ out: | |||
178 | } | 178 | } |
179 | 179 | ||
180 | /* | 180 | /* |
181 | * Congratulations to trinity for discovering this bug. | ||
182 | * mm/fremap.c's remap_file_pages() accepts any range within a single vma to | ||
183 | * convert that vma to VM_NONLINEAR; and generic_file_remap_pages() will then | ||
184 | * replace the specified range by file ptes throughout (maybe populated after). | ||
185 | * If page migration finds a page within that range, while it's still located | ||
186 | * by vma_interval_tree rather than lost to i_mmap_nonlinear list, no problem: | ||
187 | * zap_pte() clears the temporary migration entry before mmap_sem is dropped. | ||
188 | * But if the migrating page is in a part of the vma outside the range to be | ||
189 | * remapped, then it will not be cleared, and remove_migration_ptes() needs to | ||
190 | * deal with it. Fortunately, this part of the vma is of course still linear, | ||
191 | * so we just need to use linear location on the nonlinear list. | ||
192 | */ | ||
193 | static int remove_linear_migration_ptes_from_nonlinear(struct page *page, | ||
194 | struct address_space *mapping, void *arg) | ||
195 | { | ||
196 | struct vm_area_struct *vma; | ||
197 | /* hugetlbfs does not support remap_pages, so no huge pgoff worries */ | ||
198 | pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | ||
199 | unsigned long addr; | ||
200 | |||
201 | list_for_each_entry(vma, | ||
202 | &mapping->i_mmap_nonlinear, shared.nonlinear) { | ||
203 | |||
204 | addr = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); | ||
205 | if (addr >= vma->vm_start && addr < vma->vm_end) | ||
206 | remove_migration_pte(page, vma, addr, arg); | ||
207 | } | ||
208 | return SWAP_AGAIN; | ||
209 | } | ||
210 | |||
211 | /* | ||
181 | * Get rid of all migration entries and replace them by | 212 | * Get rid of all migration entries and replace them by |
182 | * references to the indicated page. | 213 | * references to the indicated page. |
183 | */ | 214 | */ |
@@ -186,6 +217,7 @@ static void remove_migration_ptes(struct page *old, struct page *new) | |||
186 | struct rmap_walk_control rwc = { | 217 | struct rmap_walk_control rwc = { |
187 | .rmap_one = remove_migration_pte, | 218 | .rmap_one = remove_migration_pte, |
188 | .arg = old, | 219 | .arg = old, |
220 | .file_nonlinear = remove_linear_migration_ptes_from_nonlinear, | ||
189 | }; | 221 | }; |
190 | 222 | ||
191 | rmap_walk(new, &rwc); | 223 | rmap_walk(new, &rwc); |
@@ -1158,7 +1190,7 @@ static struct page *new_page_node(struct page *p, unsigned long private, | |||
1158 | pm->node); | 1190 | pm->node); |
1159 | else | 1191 | else |
1160 | return alloc_pages_exact_node(pm->node, | 1192 | return alloc_pages_exact_node(pm->node, |
1161 | GFP_HIGHUSER_MOVABLE | GFP_THISNODE, 0); | 1193 | GFP_HIGHUSER_MOVABLE | __GFP_THISNODE, 0); |
1162 | } | 1194 | } |
1163 | 1195 | ||
1164 | /* | 1196 | /* |
@@ -1544,9 +1576,9 @@ static struct page *alloc_misplaced_dst_page(struct page *page, | |||
1544 | struct page *newpage; | 1576 | struct page *newpage; |
1545 | 1577 | ||
1546 | newpage = alloc_pages_exact_node(nid, | 1578 | newpage = alloc_pages_exact_node(nid, |
1547 | (GFP_HIGHUSER_MOVABLE | GFP_THISNODE | | 1579 | (GFP_HIGHUSER_MOVABLE | |
1548 | __GFP_NOMEMALLOC | __GFP_NORETRY | | 1580 | __GFP_THISNODE | __GFP_NOMEMALLOC | |
1549 | __GFP_NOWARN) & | 1581 | __GFP_NORETRY | __GFP_NOWARN) & |
1550 | ~GFP_IOFS, 0); | 1582 | ~GFP_IOFS, 0); |
1551 | 1583 | ||
1552 | return newpage; | 1584 | return newpage; |
@@ -1747,7 +1779,8 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm, | |||
1747 | goto out_dropref; | 1779 | goto out_dropref; |
1748 | 1780 | ||
1749 | new_page = alloc_pages_node(node, | 1781 | new_page = alloc_pages_node(node, |
1750 | (GFP_TRANSHUGE | GFP_THISNODE) & ~__GFP_WAIT, HPAGE_PMD_ORDER); | 1782 | (GFP_TRANSHUGE | __GFP_THISNODE) & ~__GFP_WAIT, |
1783 | HPAGE_PMD_ORDER); | ||
1751 | if (!new_page) | 1784 | if (!new_page) |
1752 | goto out_fail; | 1785 | goto out_fail; |
1753 | 1786 | ||