aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory-failure.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memory-failure.c')
-rw-r--r--mm/memory-failure.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index b7c171602ba1..fabe55046c1d 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -938,6 +938,16 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
938 BUG_ON(!PageHWPoison(p)); 938 BUG_ON(!PageHWPoison(p));
939 return SWAP_FAIL; 939 return SWAP_FAIL;
940 } 940 }
941 /*
942 * We pinned the head page for hwpoison handling,
943 * now we split the thp and we are interested in
944 * the hwpoisoned raw page, so move the refcount
945 * to it.
946 */
947 if (hpage != p) {
948 put_page(hpage);
949 get_page(p);
950 }
941 /* THP is split, so ppage should be the real poisoned page. */ 951 /* THP is split, so ppage should be the real poisoned page. */
942 ppage = p; 952 ppage = p;
943 } 953 }
@@ -1505,10 +1515,16 @@ static int soft_offline_huge_page(struct page *page, int flags)
1505 if (ret > 0) 1515 if (ret > 0)
1506 ret = -EIO; 1516 ret = -EIO;
1507 } else { 1517 } else {
1508 set_page_hwpoison_huge_page(hpage); 1518 /* overcommit hugetlb page will be freed to buddy */
1509 dequeue_hwpoisoned_huge_page(hpage); 1519 if (PageHuge(page)) {
1510 atomic_long_add(1 << compound_order(hpage), 1520 set_page_hwpoison_huge_page(hpage);
1511 &num_poisoned_pages); 1521 dequeue_hwpoisoned_huge_page(hpage);
1522 atomic_long_add(1 << compound_order(hpage),
1523 &num_poisoned_pages);
1524 } else {
1525 SetPageHWPoison(page);
1526 atomic_long_inc(&num_poisoned_pages);
1527 }
1512 } 1528 }
1513 return ret; 1529 return ret;
1514} 1530}