HWPOISON, hugetlb: set/clear PG_hwpoison bits on hugepage
To avoid race condition between concurrent memory errors on identified hugepage, we atomically test and set PG_hwpoison bit on the head page. All pages in the error hugepage are considered as hwpoisoned for now, so set and clear all PG_hwpoison bits in the hugepage with page lock of the head page held. Dependency: "HWPOISON, hugetlb: enable error handling path for hugepage" Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Andrew Morton <akpm@linux-foundation.org> Acked-by: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com>
This commit is contained in:
committed by
Andi Kleen
parent
7af446a841
commit
7013febc89
@@ -920,6 +920,22 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_page_hwpoison_huge_page(struct page *hpage)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int nr_pages = 1 << compound_order(hpage);
|
||||||
|
for (i = 0; i < nr_pages; i++)
|
||||||
|
SetPageHWPoison(hpage + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_page_hwpoison_huge_page(struct page *hpage)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int nr_pages = 1 << compound_order(hpage);
|
||||||
|
for (i = 0; i < nr_pages; i++)
|
||||||
|
ClearPageHWPoison(hpage + i);
|
||||||
|
}
|
||||||
|
|
||||||
int __memory_failure(unsigned long pfn, int trapno, int flags)
|
int __memory_failure(unsigned long pfn, int trapno, int flags)
|
||||||
{
|
{
|
||||||
struct page_state *ps;
|
struct page_state *ps;
|
||||||
@@ -1014,6 +1030,26 @@ int __memory_failure(unsigned long pfn, int trapno, int flags)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For error on the tail page, we should set PG_hwpoison
|
||||||
|
* on the head page to show that the hugepage is hwpoisoned
|
||||||
|
*/
|
||||||
|
if (PageTail(p) && TestSetPageHWPoison(hpage)) {
|
||||||
|
action_result(pfn, "hugepage already hardware poisoned",
|
||||||
|
IGNORED);
|
||||||
|
unlock_page(hpage);
|
||||||
|
put_page(hpage);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Set PG_hwpoison on all pages in an error hugepage,
|
||||||
|
* because containment is done in hugepage unit for now.
|
||||||
|
* Since we have done TestSetPageHWPoison() for the head page with
|
||||||
|
* page lock held, we can safely set PG_hwpoison bits on tail pages.
|
||||||
|
*/
|
||||||
|
if (PageHuge(p))
|
||||||
|
set_page_hwpoison_huge_page(hpage);
|
||||||
|
|
||||||
wait_on_page_writeback(p);
|
wait_on_page_writeback(p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1118,6 +1154,8 @@ int unpoison_memory(unsigned long pfn)
|
|||||||
atomic_long_dec(&mce_bad_pages);
|
atomic_long_dec(&mce_bad_pages);
|
||||||
freeit = 1;
|
freeit = 1;
|
||||||
}
|
}
|
||||||
|
if (PageHuge(p))
|
||||||
|
clear_page_hwpoison_huge_page(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
|
|
||||||
put_page(page);
|
put_page(page);
|
||||||
|
Reference in New Issue
Block a user