diff options
Diffstat (limited to 'mm')
| -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; |
