diff options
-rw-r--r-- | include/linux/migrate.h | 5 | ||||
-rw-r--r-- | mm/memory-failure.c | 15 | ||||
-rw-r--r-- | mm/migrate.c | 28 |
3 files changed, 14 insertions, 34 deletions
diff --git a/include/linux/migrate.h b/include/linux/migrate.h index a405d3dc0f61..6fe521420631 100644 --- a/include/linux/migrate.h +++ b/include/linux/migrate.h | |||
@@ -41,8 +41,6 @@ extern int migrate_page(struct address_space *, | |||
41 | struct page *, struct page *, enum migrate_mode); | 41 | struct page *, struct page *, enum migrate_mode); |
42 | extern int migrate_pages(struct list_head *l, new_page_t x, | 42 | extern int migrate_pages(struct list_head *l, new_page_t x, |
43 | unsigned long private, enum migrate_mode mode, int reason); | 43 | unsigned long private, enum migrate_mode mode, int reason); |
44 | extern int migrate_huge_page(struct page *, new_page_t x, | ||
45 | unsigned long private, enum migrate_mode mode); | ||
46 | 44 | ||
47 | extern int fail_migrate_page(struct address_space *, | 45 | extern int fail_migrate_page(struct address_space *, |
48 | struct page *, struct page *); | 46 | struct page *, struct page *); |
@@ -62,9 +60,6 @@ static inline void putback_movable_pages(struct list_head *l) {} | |||
62 | static inline int migrate_pages(struct list_head *l, new_page_t x, | 60 | static inline int migrate_pages(struct list_head *l, new_page_t x, |
63 | unsigned long private, enum migrate_mode mode, int reason) | 61 | unsigned long private, enum migrate_mode mode, int reason) |
64 | { return -ENOSYS; } | 62 | { return -ENOSYS; } |
65 | static inline int migrate_huge_page(struct page *page, new_page_t x, | ||
66 | unsigned long private, enum migrate_mode mode) | ||
67 | { return -ENOSYS; } | ||
68 | 63 | ||
69 | static inline int migrate_prep(void) { return -ENOSYS; } | 64 | static inline int migrate_prep(void) { return -ENOSYS; } |
70 | static inline int migrate_prep_local(void) { return -ENOSYS; } | 65 | static inline int migrate_prep_local(void) { return -ENOSYS; } |
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index d84c5e5331bb..e05ed31c0f61 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
@@ -1470,6 +1470,7 @@ static int soft_offline_huge_page(struct page *page, int flags) | |||
1470 | int ret; | 1470 | int ret; |
1471 | unsigned long pfn = page_to_pfn(page); | 1471 | unsigned long pfn = page_to_pfn(page); |
1472 | struct page *hpage = compound_head(page); | 1472 | struct page *hpage = compound_head(page); |
1473 | LIST_HEAD(pagelist); | ||
1473 | 1474 | ||
1474 | /* | 1475 | /* |
1475 | * This double-check of PageHWPoison is to avoid the race with | 1476 | * This double-check of PageHWPoison is to avoid the race with |
@@ -1485,12 +1486,20 @@ static int soft_offline_huge_page(struct page *page, int flags) | |||
1485 | unlock_page(hpage); | 1486 | unlock_page(hpage); |
1486 | 1487 | ||
1487 | /* Keep page count to indicate a given hugepage is isolated. */ | 1488 | /* Keep page count to indicate a given hugepage is isolated. */ |
1488 | ret = migrate_huge_page(hpage, new_page, MPOL_MF_MOVE_ALL, | 1489 | list_move(&hpage->lru, &pagelist); |
1489 | MIGRATE_SYNC); | 1490 | ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, |
1490 | put_page(hpage); | 1491 | MIGRATE_SYNC, MR_MEMORY_FAILURE); |
1491 | if (ret) { | 1492 | if (ret) { |
1492 | pr_info("soft offline: %#lx: migration failed %d, type %lx\n", | 1493 | pr_info("soft offline: %#lx: migration failed %d, type %lx\n", |
1493 | pfn, ret, page->flags); | 1494 | pfn, ret, page->flags); |
1495 | /* | ||
1496 | * We know that soft_offline_huge_page() tries to migrate | ||
1497 | * only one hugepage pointed to by hpage, so we need not | ||
1498 | * run through the pagelist here. | ||
1499 | */ | ||
1500 | putback_active_hugepage(hpage); | ||
1501 | if (ret > 0) | ||
1502 | ret = -EIO; | ||
1494 | } else { | 1503 | } else { |
1495 | set_page_hwpoison_huge_page(hpage); | 1504 | set_page_hwpoison_huge_page(hpage); |
1496 | dequeue_hwpoisoned_huge_page(hpage); | 1505 | dequeue_hwpoisoned_huge_page(hpage); |
diff --git a/mm/migrate.c b/mm/migrate.c index b44a067fee10..3ec47d3394c8 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -979,6 +979,8 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, | |||
979 | 979 | ||
980 | unlock_page(hpage); | 980 | unlock_page(hpage); |
981 | out: | 981 | out: |
982 | if (rc != -EAGAIN) | ||
983 | putback_active_hugepage(hpage); | ||
982 | put_page(new_hpage); | 984 | put_page(new_hpage); |
983 | if (result) { | 985 | if (result) { |
984 | if (rc) | 986 | if (rc) |
@@ -1066,32 +1068,6 @@ out: | |||
1066 | return rc; | 1068 | return rc; |
1067 | } | 1069 | } |
1068 | 1070 | ||
1069 | int migrate_huge_page(struct page *hpage, new_page_t get_new_page, | ||
1070 | unsigned long private, enum migrate_mode mode) | ||
1071 | { | ||
1072 | int pass, rc; | ||
1073 | |||
1074 | for (pass = 0; pass < 10; pass++) { | ||
1075 | rc = unmap_and_move_huge_page(get_new_page, private, | ||
1076 | hpage, pass > 2, mode); | ||
1077 | switch (rc) { | ||
1078 | case -ENOMEM: | ||
1079 | goto out; | ||
1080 | case -EAGAIN: | ||
1081 | /* try again */ | ||
1082 | cond_resched(); | ||
1083 | break; | ||
1084 | case MIGRATEPAGE_SUCCESS: | ||
1085 | goto out; | ||
1086 | default: | ||
1087 | rc = -EIO; | ||
1088 | goto out; | ||
1089 | } | ||
1090 | } | ||
1091 | out: | ||
1092 | return rc; | ||
1093 | } | ||
1094 | |||
1095 | #ifdef CONFIG_NUMA | 1071 | #ifdef CONFIG_NUMA |
1096 | /* | 1072 | /* |
1097 | * Move a list of individual pages | 1073 | * Move a list of individual pages |