diff options
Diffstat (limited to 'mm/migrate.c')
-rw-r--r-- | mm/migrate.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index e3a0cd3859a9..1a4bf4813780 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -67,6 +67,8 @@ int putback_lru_pages(struct list_head *l) | |||
67 | 67 | ||
68 | list_for_each_entry_safe(page, page2, l, lru) { | 68 | list_for_each_entry_safe(page, page2, l, lru) { |
69 | list_del(&page->lru); | 69 | list_del(&page->lru); |
70 | dec_zone_page_state(page, NR_ISOLATED_ANON + | ||
71 | page_is_file_cache(page)); | ||
70 | putback_lru_page(page); | 72 | putback_lru_page(page); |
71 | count++; | 73 | count++; |
72 | } | 74 | } |
@@ -147,7 +149,7 @@ out: | |||
147 | static void remove_file_migration_ptes(struct page *old, struct page *new) | 149 | static void remove_file_migration_ptes(struct page *old, struct page *new) |
148 | { | 150 | { |
149 | struct vm_area_struct *vma; | 151 | struct vm_area_struct *vma; |
150 | struct address_space *mapping = page_mapping(new); | 152 | struct address_space *mapping = new->mapping; |
151 | struct prio_tree_iter iter; | 153 | struct prio_tree_iter iter; |
152 | pgoff_t pgoff = new->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | 154 | pgoff_t pgoff = new->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); |
153 | 155 | ||
@@ -270,7 +272,7 @@ static int migrate_page_move_mapping(struct address_space *mapping, | |||
270 | pslot = radix_tree_lookup_slot(&mapping->page_tree, | 272 | pslot = radix_tree_lookup_slot(&mapping->page_tree, |
271 | page_index(page)); | 273 | page_index(page)); |
272 | 274 | ||
273 | expected_count = 2 + !!page_has_private(page); | 275 | expected_count = 2 + page_has_private(page); |
274 | if (page_count(page) != expected_count || | 276 | if (page_count(page) != expected_count || |
275 | (struct page *)radix_tree_deref_slot(pslot) != page) { | 277 | (struct page *)radix_tree_deref_slot(pslot) != page) { |
276 | spin_unlock_irq(&mapping->tree_lock); | 278 | spin_unlock_irq(&mapping->tree_lock); |
@@ -312,7 +314,10 @@ static int migrate_page_move_mapping(struct address_space *mapping, | |||
312 | */ | 314 | */ |
313 | __dec_zone_page_state(page, NR_FILE_PAGES); | 315 | __dec_zone_page_state(page, NR_FILE_PAGES); |
314 | __inc_zone_page_state(newpage, NR_FILE_PAGES); | 316 | __inc_zone_page_state(newpage, NR_FILE_PAGES); |
315 | 317 | if (PageSwapBacked(page)) { | |
318 | __dec_zone_page_state(page, NR_SHMEM); | ||
319 | __inc_zone_page_state(newpage, NR_SHMEM); | ||
320 | } | ||
316 | spin_unlock_irq(&mapping->tree_lock); | 321 | spin_unlock_irq(&mapping->tree_lock); |
317 | 322 | ||
318 | return 0; | 323 | return 0; |
@@ -664,13 +669,15 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private, | |||
664 | * needs to be effective. | 669 | * needs to be effective. |
665 | */ | 670 | */ |
666 | try_to_free_buffers(page); | 671 | try_to_free_buffers(page); |
672 | goto rcu_unlock; | ||
667 | } | 673 | } |
668 | goto rcu_unlock; | 674 | goto skip_unmap; |
669 | } | 675 | } |
670 | 676 | ||
671 | /* Establish migration ptes or remove ptes */ | 677 | /* Establish migration ptes or remove ptes */ |
672 | try_to_unmap(page, TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS); | 678 | try_to_unmap(page, TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS); |
673 | 679 | ||
680 | skip_unmap: | ||
674 | if (!page_mapped(page)) | 681 | if (!page_mapped(page)) |
675 | rc = move_to_new_page(newpage, page); | 682 | rc = move_to_new_page(newpage, page); |
676 | 683 | ||
@@ -693,6 +700,8 @@ unlock: | |||
693 | * restored. | 700 | * restored. |
694 | */ | 701 | */ |
695 | list_del(&page->lru); | 702 | list_del(&page->lru); |
703 | dec_zone_page_state(page, NR_ISOLATED_ANON + | ||
704 | page_is_file_cache(page)); | ||
696 | putback_lru_page(page); | 705 | putback_lru_page(page); |
697 | } | 706 | } |
698 | 707 | ||
@@ -737,6 +746,13 @@ int migrate_pages(struct list_head *from, | |||
737 | struct page *page2; | 746 | struct page *page2; |
738 | int swapwrite = current->flags & PF_SWAPWRITE; | 747 | int swapwrite = current->flags & PF_SWAPWRITE; |
739 | int rc; | 748 | int rc; |
749 | unsigned long flags; | ||
750 | |||
751 | local_irq_save(flags); | ||
752 | list_for_each_entry(page, from, lru) | ||
753 | __inc_zone_page_state(page, NR_ISOLATED_ANON + | ||
754 | page_is_file_cache(page)); | ||
755 | local_irq_restore(flags); | ||
740 | 756 | ||
741 | if (!swapwrite) | 757 | if (!swapwrite) |
742 | current->flags |= PF_SWAPWRITE; | 758 | current->flags |= PF_SWAPWRITE; |