summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/migrate.h5
-rw-r--r--mm/memory-failure.c15
-rw-r--r--mm/migrate.c28
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);
42extern int migrate_pages(struct list_head *l, new_page_t x, 42extern 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);
44extern int migrate_huge_page(struct page *, new_page_t x,
45 unsigned long private, enum migrate_mode mode);
46 44
47extern int fail_migrate_page(struct address_space *, 45extern 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) {}
62static inline int migrate_pages(struct list_head *l, new_page_t x, 60static 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; }
65static 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
69static inline int migrate_prep(void) { return -ENOSYS; } 64static inline int migrate_prep(void) { return -ENOSYS; }
70static inline int migrate_prep_local(void) { return -ENOSYS; } 65static 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);
981out: 981out:
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
1069int 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 }
1091out:
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