diff options
Diffstat (limited to 'mm/migrate.c')
-rw-r--r-- | mm/migrate.c | 65 |
1 files changed, 21 insertions, 44 deletions
diff --git a/mm/migrate.c b/mm/migrate.c index be26d5cbe56b..fdce3a29fc4c 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -932,15 +932,8 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, | |||
932 | if (anon_vma) | 932 | if (anon_vma) |
933 | put_anon_vma(anon_vma); | 933 | put_anon_vma(anon_vma); |
934 | unlock_page(hpage); | 934 | unlock_page(hpage); |
935 | |||
936 | out: | 935 | out: |
937 | if (rc != -EAGAIN) { | ||
938 | list_del(&hpage->lru); | ||
939 | put_page(hpage); | ||
940 | } | ||
941 | |||
942 | put_page(new_hpage); | 936 | put_page(new_hpage); |
943 | |||
944 | if (result) { | 937 | if (result) { |
945 | if (rc) | 938 | if (rc) |
946 | *result = rc; | 939 | *result = rc; |
@@ -1016,48 +1009,32 @@ out: | |||
1016 | return nr_failed + retry; | 1009 | return nr_failed + retry; |
1017 | } | 1010 | } |
1018 | 1011 | ||
1019 | int migrate_huge_pages(struct list_head *from, | 1012 | int migrate_huge_page(struct page *hpage, new_page_t get_new_page, |
1020 | new_page_t get_new_page, unsigned long private, bool offlining, | 1013 | unsigned long private, bool offlining, |
1021 | enum migrate_mode mode) | 1014 | enum migrate_mode mode) |
1022 | { | 1015 | { |
1023 | int retry = 1; | 1016 | int pass, rc; |
1024 | int nr_failed = 0; | 1017 | |
1025 | int pass = 0; | 1018 | for (pass = 0; pass < 10; pass++) { |
1026 | struct page *page; | 1019 | rc = unmap_and_move_huge_page(get_new_page, |
1027 | struct page *page2; | 1020 | private, hpage, pass > 2, offlining, |
1028 | int rc; | 1021 | mode); |
1029 | 1022 | switch (rc) { | |
1030 | for (pass = 0; pass < 10 && retry; pass++) { | 1023 | case -ENOMEM: |
1031 | retry = 0; | 1024 | goto out; |
1032 | 1025 | case -EAGAIN: | |
1033 | list_for_each_entry_safe(page, page2, from, lru) { | 1026 | /* try again */ |
1034 | cond_resched(); | 1027 | cond_resched(); |
1035 | 1028 | break; | |
1036 | rc = unmap_and_move_huge_page(get_new_page, | 1029 | case 0: |
1037 | private, page, pass > 2, offlining, | 1030 | goto out; |
1038 | mode); | 1031 | default: |
1039 | 1032 | rc = -EIO; | |
1040 | switch(rc) { | 1033 | goto out; |
1041 | case -ENOMEM: | ||
1042 | goto out; | ||
1043 | case -EAGAIN: | ||
1044 | retry++; | ||
1045 | break; | ||
1046 | case 0: | ||
1047 | break; | ||
1048 | default: | ||
1049 | /* Permanent failure */ | ||
1050 | nr_failed++; | ||
1051 | break; | ||
1052 | } | ||
1053 | } | 1034 | } |
1054 | } | 1035 | } |
1055 | rc = 0; | ||
1056 | out: | 1036 | out: |
1057 | if (rc) | 1037 | return rc; |
1058 | return rc; | ||
1059 | |||
1060 | return nr_failed + retry; | ||
1061 | } | 1038 | } |
1062 | 1039 | ||
1063 | #ifdef CONFIG_NUMA | 1040 | #ifdef CONFIG_NUMA |