Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 232730
b: refs/heads/master
c: a6d30dd
h: refs/heads/master
v: v3
  • Loading branch information
Jin Dongming authored and Linus Torvalds committed Feb 3, 2011
1 parent d3f5b9e commit a74cd20
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: efeda7a41e09efce506a68c3549b60b16dd7dedd
refs/heads/master: a6d30dddae4648837be5a0c0cb2c0ae9ad0377db
7 changes: 6 additions & 1 deletion trunk/mm/huge_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,12 @@ static void __split_huge_page_refcount(struct page *page)
/* after clearing PageTail the gup refcount can be released */
smp_mb();

page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
/*
* retain hwpoison flag of the poisoned tail page:
* fix for the unsuitable process killed on Guest Machine(KVM)
* by the memory-failure.
*/
page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP | __PG_HWPOISON;
page_tail->flags |= (page->flags &
((1L << PG_referenced) |
(1L << PG_swapbacked) |
Expand Down
27 changes: 22 additions & 5 deletions trunk/mm/memory-failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
int ret;
int kill = 1;
struct page *hpage = compound_head(p);
struct page *ppage;

if (PageReserved(p) || PageSlab(p))
return SWAP_SUCCESS;
Expand Down Expand Up @@ -894,6 +895,14 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
}
}

/*
* ppage: poisoned page
* if p is regular page(4k page)
* ppage == real poisoned page;
* else p is hugetlb or THP, ppage == head page.
*/
ppage = hpage;

if (PageTransHuge(hpage)) {
/*
* Verify that this isn't a hugetlbfs head page, the check for
Expand All @@ -919,6 +928,8 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
BUG_ON(!PageHWPoison(p));
return SWAP_FAIL;
}
/* THP is split, so ppage should be the real poisoned page. */
ppage = p;
}
}

Expand All @@ -931,12 +942,18 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
* there's nothing that can be done.
*/
if (kill)
collect_procs(hpage, &tokill);
collect_procs(ppage, &tokill);

ret = try_to_unmap(hpage, ttu);
if (hpage != ppage)
lock_page_nosync(ppage);

ret = try_to_unmap(ppage, ttu);
if (ret != SWAP_SUCCESS)
printk(KERN_ERR "MCE %#lx: failed to unmap page (mapcount=%d)\n",
pfn, page_mapcount(hpage));
pfn, page_mapcount(ppage));

if (hpage != ppage)
unlock_page(ppage);

/*
* Now that the dirty bit has been propagated to the
Expand All @@ -947,7 +964,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
* use a more force-full uncatchable kill to prevent
* any accesses to the poisoned memory.
*/
kill_procs_ao(&tokill, !!PageDirty(hpage), trapno,
kill_procs_ao(&tokill, !!PageDirty(ppage), trapno,
ret != SWAP_SUCCESS, p, pfn);

return ret;
Expand Down Expand Up @@ -1090,7 +1107,7 @@ int __memory_failure(unsigned long pfn, int trapno, int flags)
* 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)) {
if (PageHuge(p) && PageTail(p) && TestSetPageHWPoison(hpage)) {
action_result(pfn, "hugepage already hardware poisoned",
IGNORED);
unlock_page(hpage);
Expand Down

0 comments on commit a74cd20

Please sign in to comment.