aboutsummaryrefslogtreecommitdiffstats
path: root/mm/migrate.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/migrate.c')
-rw-r--r--mm/migrate.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/mm/migrate.c b/mm/migrate.c
index be3f141e53a4..2803a6698dd6 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -168,19 +168,19 @@ retry:
168/* 168/*
169 * Remove references for a page and establish the new page with the correct 169 * Remove references for a page and establish the new page with the correct
170 * basic settings to be able to stop accesses to the page. 170 * basic settings to be able to stop accesses to the page.
171 *
172 * The number of remaining references must be:
173 * 1 for anonymous pages without a mapping
174 * 2 for pages with a mapping
175 * 3 for pages with a mapping and PagePrivate set.
171 */ 176 */
172static int migrate_page_remove_references(struct page *newpage, 177static int migrate_page_remove_references(struct page *newpage,
173 struct page *page, int nr_refs) 178 struct page *page)
174{ 179{
175 struct address_space *mapping = page_mapping(page); 180 struct address_space *mapping = page_mapping(page);
176 struct page **radix_pointer; 181 struct page **radix_pointer;
177 182
178 /* 183 if (!mapping)
179 * Avoid doing any of the following work if the page count
180 * indicates that the page is in use or truncate has removed
181 * the page.
182 */
183 if (!mapping || page_mapcount(page) + nr_refs != page_count(page))
184 return -EAGAIN; 184 return -EAGAIN;
185 185
186 /* 186 /*
@@ -218,7 +218,8 @@ static int migrate_page_remove_references(struct page *newpage,
218 &mapping->page_tree, 218 &mapping->page_tree,
219 page_index(page)); 219 page_index(page));
220 220
221 if (!page_mapping(page) || page_count(page) != nr_refs || 221 if (!page_mapping(page) ||
222 page_count(page) != 2 + !!PagePrivate(page) ||
222 *radix_pointer != page) { 223 *radix_pointer != page) {
223 write_unlock_irq(&mapping->tree_lock); 224 write_unlock_irq(&mapping->tree_lock);
224 return -EAGAIN; 225 return -EAGAIN;
@@ -309,7 +310,7 @@ int migrate_page(struct page *newpage, struct page *page)
309 310
310 BUG_ON(PageWriteback(page)); /* Writeback must be complete */ 311 BUG_ON(PageWriteback(page)); /* Writeback must be complete */
311 312
312 rc = migrate_page_remove_references(newpage, page, 2); 313 rc = migrate_page_remove_references(newpage, page);
313 314
314 if (rc) 315 if (rc)
315 return rc; 316 return rc;
@@ -348,7 +349,7 @@ int buffer_migrate_page(struct page *newpage, struct page *page)
348 349
349 head = page_buffers(page); 350 head = page_buffers(page);
350 351
351 rc = migrate_page_remove_references(newpage, page, 3); 352 rc = migrate_page_remove_references(newpage, page);
352 353
353 if (rc) 354 if (rc)
354 return rc; 355 return rc;