aboutsummaryrefslogtreecommitdiffstats
path: root/mm/migrate.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/migrate.c')
-rw-r--r--mm/migrate.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/mm/migrate.c b/mm/migrate.c
index 34d8ada053e4..37c73b902008 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -49,9 +49,8 @@ int isolate_lru_page(struct page *page, struct list_head *pagelist)
49 struct zone *zone = page_zone(page); 49 struct zone *zone = page_zone(page);
50 50
51 spin_lock_irq(&zone->lru_lock); 51 spin_lock_irq(&zone->lru_lock);
52 if (PageLRU(page)) { 52 if (PageLRU(page) && get_page_unless_zero(page)) {
53 ret = 0; 53 ret = 0;
54 get_page(page);
55 ClearPageLRU(page); 54 ClearPageLRU(page);
56 if (PageActive(page)) 55 if (PageActive(page))
57 del_page_from_active_list(zone, page); 56 del_page_from_active_list(zone, page);
@@ -632,18 +631,35 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
632 goto unlock; 631 goto unlock;
633 wait_on_page_writeback(page); 632 wait_on_page_writeback(page);
634 } 633 }
635
636 /* 634 /*
637 * Establish migration ptes or remove ptes 635 * By try_to_unmap(), page->mapcount goes down to 0 here. In this case,
636 * we cannot notice that anon_vma is freed while we migrates a page.
637 * This rcu_read_lock() delays freeing anon_vma pointer until the end
638 * of migration. File cache pages are no problem because of page_lock()
639 */
640 rcu_read_lock();
641 /*
642 * This is a corner case handling.
643 * When a new swap-cache is read into, it is linked to LRU
644 * and treated as swapcache but has no rmap yet.
645 * Calling try_to_unmap() against a page->mapping==NULL page is
646 * BUG. So handle it here.
638 */ 647 */
648 if (!page->mapping)
649 goto rcu_unlock;
650 /* Establish migration ptes or remove ptes */
639 try_to_unmap(page, 1); 651 try_to_unmap(page, 1);
652
640 if (!page_mapped(page)) 653 if (!page_mapped(page))
641 rc = move_to_new_page(newpage, page); 654 rc = move_to_new_page(newpage, page);
642 655
643 if (rc) 656 if (rc)
644 remove_migration_ptes(page, page); 657 remove_migration_ptes(page, page);
658rcu_unlock:
659 rcu_read_unlock();
645 660
646unlock: 661unlock:
662
647 unlock_page(page); 663 unlock_page(page);
648 664
649 if (rc != -EAGAIN) { 665 if (rc != -EAGAIN) {