From: Naoya Horiguchi <naoya.horiguchi@xxxxxxx> Now hwpoisoned hugepage is expected to be !HPageMigratable, so grabbing hugepage for unpoison should negate the check from that for poisoning. This patch implements it by logical XOR. Signed-off-by: Naoya Horiguchi <naoya.horiguchi@xxxxxxx> --- include/linux/hugetlb.h | 5 +++-- mm/hugetlb.c | 4 ++-- mm/memory-failure.c | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 689e69cb556b..99b7ded651f6 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -171,7 +171,7 @@ bool hugetlb_reserve_pages(struct inode *inode, long from, long to, long hugetlb_unreserve_pages(struct inode *inode, long start, long end, long freed); bool isolate_huge_page(struct page *page, struct list_head *list); -int get_hwpoison_huge_page(struct page *page, bool *hugetlb); +int get_hwpoison_huge_page(struct page *page, bool *hugetlb, bool unpoison); int get_huge_page_for_hwpoison(unsigned long pfn, int flags); void putback_active_hugepage(struct page *page); void move_hugetlb_state(struct page *oldpage, struct page *newpage, int reason); @@ -377,7 +377,8 @@ static inline bool isolate_huge_page(struct page *page, struct list_head *list) return false; } -static inline int get_hwpoison_huge_page(struct page *page, bool *hugetlb) +static inline int get_hwpoison_huge_page(struct page *page, bool *hugetlb, + bool unpoison) { return 0; } diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 95b1db852ca9..0fbdfa753b54 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -6788,7 +6788,7 @@ bool isolate_huge_page(struct page *page, struct list_head *list) return ret; } -int get_hwpoison_huge_page(struct page *page, bool *hugetlb) +int get_hwpoison_huge_page(struct page *page, bool *hugetlb, bool unpoison) { int ret = 0; @@ -6798,7 +6798,7 @@ int get_hwpoison_huge_page(struct page *page, bool *hugetlb) *hugetlb = true; if (HPageFreed(page)) ret = 0; - else if (HPageMigratable(page)) + else if (!unpoison != !HPageMigratable(page)) ret = get_page_unless_zero(page); else ret = -EBUSY; diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 4a2e22bf0983..b5ee3cbc7fbc 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1190,7 +1190,7 @@ static int __get_hwpoison_page(struct page *page, unsigned long flags) int ret = 0; bool hugetlb = false; - ret = get_hwpoison_huge_page(head, &hugetlb); + ret = get_hwpoison_huge_page(head, &hugetlb, false); if (hugetlb) return ret; @@ -1283,7 +1283,7 @@ static int __get_unpoison_page(struct page *page) int ret = 0; bool hugetlb = false; - ret = get_hwpoison_huge_page(head, &hugetlb); + ret = get_hwpoison_huge_page(head, &hugetlb, true); if (hugetlb) return ret; -- 2.25.1