aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNaoya Horiguchi <n-horiguchi@ah.jp.nec.com>2010-09-07 21:19:32 -0400
committerAndi Kleen <ak@linux.intel.com>2010-10-08 03:32:44 -0400
commit998b4382c1d75a6fd3b0e334dae3ab33bd074d99 (patch)
tree666c8eaad844df0447870f1e6fada4f0fb8007cd
parent6b0cd00bc396daf5c2dcf17a8d82055335341f46 (diff)
hugetlb: fix metadata corruption in hugetlb_fault()
Since the PageHWPoison() check is for avoiding hwpoisoned page remained in pagecache mapping to the process, it should be done in "found in pagecache" branch, not in the common path. Otherwise, metadata corruption occurs if memory failure happens between alloc_huge_page() and lock_page() because page fault fails with metadata changes remained (such as refcount, mapcount, etc.) This patch moves the check to "found in pagecache" branch and fix the problem. ChangeLog since v2: - remove retry check in "new allocation" path. - make description more detailed - change patch name from "HWPOISON, hugetlb: move PG_HWPoison bit check" Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com> Acked-by: Mel Gorman <mel@csn.ul.ie> Reviewed-by: Wu Fengguang <fengguang.wu@intel.com> Reviewed-by: Christoph Lameter <cl@linux.com> Signed-off-by: Andi Kleen <ak@linux.intel.com>
-rw-r--r--mm/hugetlb.c21
1 files changed, 9 insertions, 12 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index c03273807182..bd031a4c738e 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2515,22 +2515,19 @@ retry:
2515 hugepage_add_new_anon_rmap(page, vma, address); 2515 hugepage_add_new_anon_rmap(page, vma, address);
2516 } 2516 }
2517 } else { 2517 } else {
2518 /*
2519 * If memory error occurs between mmap() and fault, some process
2520 * don't have hwpoisoned swap entry for errored virtual address.
2521 * So we need to block hugepage fault by PG_hwpoison bit check.
2522 */
2523 if (unlikely(PageHWPoison(page))) {
2524 ret = VM_FAULT_HWPOISON;
2525 goto backout_unlocked;
2526 }
2518 page_dup_rmap(page); 2527 page_dup_rmap(page);
2519 } 2528 }
2520 2529
2521 /* 2530 /*
2522 * Since memory error handler replaces pte into hwpoison swap entry
2523 * at the time of error handling, a process which reserved but not have
2524 * the mapping to the error hugepage does not have hwpoison swap entry.
2525 * So we need to block accesses from such a process by checking
2526 * PG_hwpoison bit here.
2527 */
2528 if (unlikely(PageHWPoison(page))) {
2529 ret = VM_FAULT_HWPOISON;
2530 goto backout_unlocked;
2531 }
2532
2533 /*
2534 * If we are going to COW a private mapping later, we examine the 2531 * If we are going to COW a private mapping later, we examine the
2535 * pending reservations for this page now. This will ensure that 2532 * pending reservations for this page now. This will ensure that
2536 * any allocations necessary to record that reservation occur outside 2533 * any allocations necessary to record that reservation occur outside