diff options
Diffstat (limited to 'mm/migrate.c')
-rw-r--r-- | mm/migrate.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index 7452a00bbb50..842ecd7aaf7f 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -740,6 +740,15 @@ static int move_to_new_page(struct page *newpage, struct page *page, | |||
740 | if (PageSwapBacked(page)) | 740 | if (PageSwapBacked(page)) |
741 | SetPageSwapBacked(newpage); | 741 | SetPageSwapBacked(newpage); |
742 | 742 | ||
743 | /* | ||
744 | * Indirectly called below, migrate_page_copy() copies PG_dirty and thus | ||
745 | * needs newpage's memcg set to transfer memcg dirty page accounting. | ||
746 | * So perform memcg migration in two steps: | ||
747 | * 1. set newpage->mem_cgroup (here) | ||
748 | * 2. clear page->mem_cgroup (below) | ||
749 | */ | ||
750 | set_page_memcg(newpage, page_memcg(page)); | ||
751 | |||
743 | mapping = page_mapping(page); | 752 | mapping = page_mapping(page); |
744 | if (!mapping) | 753 | if (!mapping) |
745 | rc = migrate_page(mapping, newpage, page, mode); | 754 | rc = migrate_page(mapping, newpage, page, mode); |
@@ -756,9 +765,10 @@ static int move_to_new_page(struct page *newpage, struct page *page, | |||
756 | rc = fallback_migrate_page(mapping, newpage, page, mode); | 765 | rc = fallback_migrate_page(mapping, newpage, page, mode); |
757 | 766 | ||
758 | if (rc != MIGRATEPAGE_SUCCESS) { | 767 | if (rc != MIGRATEPAGE_SUCCESS) { |
768 | set_page_memcg(newpage, NULL); | ||
759 | newpage->mapping = NULL; | 769 | newpage->mapping = NULL; |
760 | } else { | 770 | } else { |
761 | mem_cgroup_migrate(page, newpage, false); | 771 | set_page_memcg(page, NULL); |
762 | if (page_was_mapped) | 772 | if (page_was_mapped) |
763 | remove_migration_ptes(page, newpage); | 773 | remove_migration_ptes(page, newpage); |
764 | page->mapping = NULL; | 774 | page->mapping = NULL; |