aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2012-07-31 19:42:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-31 21:42:40 -0400
commit189ebff2894a9d0f4e250dd1e154d282ef0a6779 (patch)
treee498573190660e2cfe6f64ff3fcc8cf3d44a58da
parent24669e58477e2752c1fbca9c1c988e9dd0d79d15 (diff)
hugetlb: simplify migrate_huge_page()
Since we migrate only one hugepage, don't use linked list for passing the page around. Directly pass the page that need to be migrated as argument. This also removes the usage of page->lru in the migrate path. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: David Rientjes <rientjes@google.com> Cc: Hillf Danton <dhillf@gmail.com> Reviewed-by: Michal Hocko <mhocko@suse.cz> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/migrate.h4
-rw-r--r--mm/memory-failure.c15
-rw-r--r--mm/migrate.c65
3 files changed, 27 insertions, 57 deletions
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index 855c337b20c3..ce7e6671968b 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -15,7 +15,7 @@ extern int migrate_page(struct address_space *,
15extern int migrate_pages(struct list_head *l, new_page_t x, 15extern int migrate_pages(struct list_head *l, new_page_t x,
16 unsigned long private, bool offlining, 16 unsigned long private, bool offlining,
17 enum migrate_mode mode); 17 enum migrate_mode mode);
18extern int migrate_huge_pages(struct list_head *l, new_page_t x, 18extern int migrate_huge_page(struct page *, new_page_t x,
19 unsigned long private, bool offlining, 19 unsigned long private, bool offlining,
20 enum migrate_mode mode); 20 enum migrate_mode mode);
21 21
@@ -36,7 +36,7 @@ static inline void putback_lru_pages(struct list_head *l) {}
36static inline int migrate_pages(struct list_head *l, new_page_t x, 36static inline int migrate_pages(struct list_head *l, new_page_t x,
37 unsigned long private, bool offlining, 37 unsigned long private, bool offlining,
38 enum migrate_mode mode) { return -ENOSYS; } 38 enum migrate_mode mode) { return -ENOSYS; }
39static inline int migrate_huge_pages(struct list_head *l, new_page_t x, 39static inline int migrate_huge_page(struct page *page, new_page_t x,
40 unsigned long private, bool offlining, 40 unsigned long private, bool offlining,
41 enum migrate_mode mode) { return -ENOSYS; } 41 enum migrate_mode mode) { return -ENOSYS; }
42 42
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 6de0d613bbe6..b04ff2d6f73d 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1416,7 +1416,6 @@ static int soft_offline_huge_page(struct page *page, int flags)
1416 int ret; 1416 int ret;
1417 unsigned long pfn = page_to_pfn(page); 1417 unsigned long pfn = page_to_pfn(page);
1418 struct page *hpage = compound_head(page); 1418 struct page *hpage = compound_head(page);
1419 LIST_HEAD(pagelist);
1420 1419
1421 ret = get_any_page(page, pfn, flags); 1420 ret = get_any_page(page, pfn, flags);
1422 if (ret < 0) 1421 if (ret < 0)
@@ -1431,24 +1430,18 @@ static int soft_offline_huge_page(struct page *page, int flags)
1431 } 1430 }
1432 1431
1433 /* Keep page count to indicate a given hugepage is isolated. */ 1432 /* Keep page count to indicate a given hugepage is isolated. */
1434 1433 ret = migrate_huge_page(hpage, new_page, MPOL_MF_MOVE_ALL, false,
1435 list_add(&hpage->lru, &pagelist);
1436 ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, false,
1437 MIGRATE_SYNC); 1434 MIGRATE_SYNC);
1435 put_page(hpage);
1438 if (ret) { 1436 if (ret) {
1439 struct page *page1, *page2;
1440 list_for_each_entry_safe(page1, page2, &pagelist, lru)
1441 put_page(page1);
1442
1443 pr_info("soft offline: %#lx: migration failed %d, type %lx\n", 1437 pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
1444 pfn, ret, page->flags); 1438 pfn, ret, page->flags);
1445 if (ret > 0)
1446 ret = -EIO;
1447 return ret; 1439 return ret;
1448 } 1440 }
1449done: 1441done:
1450 if (!PageHWPoison(hpage)) 1442 if (!PageHWPoison(hpage))
1451 atomic_long_add(1 << compound_trans_order(hpage), &mce_bad_pages); 1443 atomic_long_add(1 << compound_trans_order(hpage),
1444 &mce_bad_pages);
1452 set_page_hwpoison_huge_page(hpage); 1445 set_page_hwpoison_huge_page(hpage);
1453 dequeue_hwpoisoned_huge_page(hpage); 1446 dequeue_hwpoisoned_huge_page(hpage);
1454 /* keep elevated page count for bad page */ 1447 /* keep elevated page count for bad page */
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
936out: 935out:
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
1019int migrate_huge_pages(struct list_head *from, 1012int 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;
1056out: 1036out:
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