diff options
Diffstat (limited to 'mm/migrate.c')
-rw-r--r-- | mm/migrate.c | 64 |
1 files changed, 40 insertions, 24 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index bd3fdc202e8b..c74412b381ff 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -915,6 +915,19 @@ out_unlock: | |||
915 | put_anon_vma(anon_vma); | 915 | put_anon_vma(anon_vma); |
916 | unlock_page(page); | 916 | unlock_page(page); |
917 | out: | 917 | out: |
918 | /* | ||
919 | * If migration is successful, decrease refcount of the newpage | ||
920 | * which will not free the page because new page owner increased | ||
921 | * refcounter. As well, if it is LRU page, add the page to LRU | ||
922 | * list in here. | ||
923 | */ | ||
924 | if (rc == MIGRATEPAGE_SUCCESS) { | ||
925 | if (unlikely(__is_movable_balloon_page(newpage))) | ||
926 | put_page(newpage); | ||
927 | else | ||
928 | putback_lru_page(newpage); | ||
929 | } | ||
930 | |||
918 | return rc; | 931 | return rc; |
919 | } | 932 | } |
920 | 933 | ||
@@ -948,6 +961,12 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page, | |||
948 | 961 | ||
949 | if (page_count(page) == 1) { | 962 | if (page_count(page) == 1) { |
950 | /* page was freed from under us. So we are done. */ | 963 | /* page was freed from under us. So we are done. */ |
964 | ClearPageActive(page); | ||
965 | ClearPageUnevictable(page); | ||
966 | if (put_new_page) | ||
967 | put_new_page(newpage, private); | ||
968 | else | ||
969 | put_page(newpage); | ||
951 | goto out; | 970 | goto out; |
952 | } | 971 | } |
953 | 972 | ||
@@ -960,10 +979,8 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page, | |||
960 | } | 979 | } |
961 | 980 | ||
962 | rc = __unmap_and_move(page, newpage, force, mode); | 981 | rc = __unmap_and_move(page, newpage, force, mode); |
963 | if (rc == MIGRATEPAGE_SUCCESS) { | 982 | if (rc == MIGRATEPAGE_SUCCESS) |
964 | put_new_page = NULL; | ||
965 | set_page_owner_migrate_reason(newpage, reason); | 983 | set_page_owner_migrate_reason(newpage, reason); |
966 | } | ||
967 | 984 | ||
968 | out: | 985 | out: |
969 | if (rc != -EAGAIN) { | 986 | if (rc != -EAGAIN) { |
@@ -976,34 +993,33 @@ out: | |||
976 | list_del(&page->lru); | 993 | list_del(&page->lru); |
977 | dec_zone_page_state(page, NR_ISOLATED_ANON + | 994 | dec_zone_page_state(page, NR_ISOLATED_ANON + |
978 | page_is_file_cache(page)); | 995 | page_is_file_cache(page)); |
979 | /* Soft-offlined page shouldn't go through lru cache list */ | 996 | } |
980 | if (reason == MR_MEMORY_FAILURE && rc == MIGRATEPAGE_SUCCESS) { | 997 | |
998 | /* | ||
999 | * If migration is successful, releases reference grabbed during | ||
1000 | * isolation. Otherwise, restore the page to right list unless | ||
1001 | * we want to retry. | ||
1002 | */ | ||
1003 | if (rc == MIGRATEPAGE_SUCCESS) { | ||
1004 | put_page(page); | ||
1005 | if (reason == MR_MEMORY_FAILURE) { | ||
981 | /* | 1006 | /* |
982 | * With this release, we free successfully migrated | 1007 | * Set PG_HWPoison on just freed page |
983 | * page and set PG_HWPoison on just freed page | 1008 | * intentionally. Although it's rather weird, |
984 | * intentionally. Although it's rather weird, it's how | 1009 | * it's how HWPoison flag works at the moment. |
985 | * HWPoison flag works at the moment. | ||
986 | */ | 1010 | */ |
987 | put_page(page); | ||
988 | if (!test_set_page_hwpoison(page)) | 1011 | if (!test_set_page_hwpoison(page)) |
989 | num_poisoned_pages_inc(); | 1012 | num_poisoned_pages_inc(); |
990 | } else | 1013 | } |
1014 | } else { | ||
1015 | if (rc != -EAGAIN) | ||
991 | putback_lru_page(page); | 1016 | putback_lru_page(page); |
1017 | if (put_new_page) | ||
1018 | put_new_page(newpage, private); | ||
1019 | else | ||
1020 | put_page(newpage); | ||
992 | } | 1021 | } |
993 | 1022 | ||
994 | /* | ||
995 | * If migration was not successful and there's a freeing callback, use | ||
996 | * it. Otherwise, putback_lru_page() will drop the reference grabbed | ||
997 | * during isolation. | ||
998 | */ | ||
999 | if (put_new_page) | ||
1000 | put_new_page(newpage, private); | ||
1001 | else if (unlikely(__is_movable_balloon_page(newpage))) { | ||
1002 | /* drop our reference, page already in the balloon */ | ||
1003 | put_page(newpage); | ||
1004 | } else | ||
1005 | putback_lru_page(newpage); | ||
1006 | |||
1007 | if (result) { | 1023 | if (result) { |
1008 | if (rc) | 1024 | if (rc) |
1009 | *result = rc; | 1025 | *result = rc; |