aboutsummaryrefslogtreecommitdiffstats
path: root/mm/migrate.c
diff options
context:
space:
mode:
authorHugh Dickins <hughd@google.com>2015-11-05 21:49:53 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-05 22:34:48 -0500
commit5c3f9a67371643b6faa987622bc1b67667bab848 (patch)
tree6c29472764822d11cd53509a7bc93aa3f6803e1c /mm/migrate.c
parent7db7671f835ccad66db20154ac1274140937d9b7 (diff)
mm: page migration remove_migration_ptes at lock+unlock level
Clean up page migration a little more by calling remove_migration_ptes() from the same level, on success or on failure, from __unmap_and_move() or from unmap_and_move_huge_page(). Don't reset page->mapping of a PageAnon old page in move_to_new_page(), leave that to when the page is freed. Except for here in page migration, it has been an invariant that a PageAnon (bit set in page->mapping) page stays PageAnon until it is freed, and I think we're safer to keep to that. And with the above rearrangement, it's necessary because zap_pte_range() wants to identify whether a migration entry represents a file or an anon page, to update the appropriate rss stats without waiting on it. Signed-off-by: Hugh Dickins <hughd@google.com> Cc: Christoph Lameter <cl@linux.com> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> Cc: Rik van Riel <riel@redhat.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Sasha Levin <sasha.levin@oracle.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/migrate.c')
-rw-r--r--mm/migrate.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/mm/migrate.c b/mm/migrate.c
index 6d7774ef0e6c..7b44ebdf2d26 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -722,7 +722,7 @@ static int fallback_migrate_page(struct address_space *mapping,
722 * MIGRATEPAGE_SUCCESS - success 722 * MIGRATEPAGE_SUCCESS - success
723 */ 723 */
724static int move_to_new_page(struct page *newpage, struct page *page, 724static int move_to_new_page(struct page *newpage, struct page *page,
725 int page_was_mapped, enum migrate_mode mode) 725 enum migrate_mode mode)
726{ 726{
727 struct address_space *mapping; 727 struct address_space *mapping;
728 int rc; 728 int rc;
@@ -755,19 +755,21 @@ static int move_to_new_page(struct page *newpage, struct page *page,
755 * space which also has its own migratepage callback. This 755 * space which also has its own migratepage callback. This
756 * is the most common path for page migration. 756 * is the most common path for page migration.
757 */ 757 */
758 rc = mapping->a_ops->migratepage(mapping, 758 rc = mapping->a_ops->migratepage(mapping, newpage, page, mode);
759 newpage, page, mode);
760 else 759 else
761 rc = fallback_migrate_page(mapping, newpage, page, mode); 760 rc = fallback_migrate_page(mapping, newpage, page, mode);
762 761
763 if (rc != MIGRATEPAGE_SUCCESS) { 762 /*
763 * When successful, old pagecache page->mapping must be cleared before
764 * page is freed; but stats require that PageAnon be left as PageAnon.
765 */
766 if (rc == MIGRATEPAGE_SUCCESS) {
767 set_page_memcg(page, NULL);
768 if (!PageAnon(page))
769 page->mapping = NULL;
770 } else {
764 set_page_memcg(newpage, NULL); 771 set_page_memcg(newpage, NULL);
765 newpage->mapping = NULL; 772 newpage->mapping = NULL;
766 } else {
767 set_page_memcg(page, NULL);
768 if (page_was_mapped)
769 remove_migration_ptes(page, newpage);
770 page->mapping = NULL;
771 } 773 }
772 return rc; 774 return rc;
773} 775}
@@ -902,10 +904,11 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
902 } 904 }
903 905
904 if (!page_mapped(page)) 906 if (!page_mapped(page))
905 rc = move_to_new_page(newpage, page, page_was_mapped, mode); 907 rc = move_to_new_page(newpage, page, mode);
906 908
907 if (rc && page_was_mapped) 909 if (page_was_mapped)
908 remove_migration_ptes(page, page); 910 remove_migration_ptes(page,
911 rc == MIGRATEPAGE_SUCCESS ? newpage : page);
909 912
910out_unlock_both: 913out_unlock_both:
911 unlock_page(newpage); 914 unlock_page(newpage);
@@ -1066,10 +1069,11 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
1066 } 1069 }
1067 1070
1068 if (!page_mapped(hpage)) 1071 if (!page_mapped(hpage))
1069 rc = move_to_new_page(new_hpage, hpage, page_was_mapped, mode); 1072 rc = move_to_new_page(new_hpage, hpage, mode);
1070 1073
1071 if (rc != MIGRATEPAGE_SUCCESS && page_was_mapped) 1074 if (page_was_mapped)
1072 remove_migration_ptes(hpage, hpage); 1075 remove_migration_ptes(hpage,
1076 rc == MIGRATEPAGE_SUCCESS ? new_hpage : hpage);
1073 1077
1074 unlock_page(new_hpage); 1078 unlock_page(new_hpage);
1075 1079