1 From a8bda28d87c38c6aa93de28ba5d30cc18e865a11 Mon Sep 17 00:00:00 2001
2 From: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
3 Date: Wed, 11 Feb 2015 15:25:28 -0800
4 Subject: mm/hugetlb: add migration/hwpoisoned entry check in hugetlb_change_protection
6 From: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
8 commit a8bda28d87c38c6aa93de28ba5d30cc18e865a11 upstream.
10 There is a race condition between hugepage migration and
11 change_protection(), where hugetlb_change_protection() doesn't care about
12 migration entries and wrongly overwrites them. That causes unexpected
13 results like kernel crash. HWPoison entries also can cause the same
16 This patch adds is_hugetlb_entry_(migration|hwpoisoned) check in this
17 function to do proper actions.
19 Fixes: 290408d4a2 ("hugetlb: hugepage migration core")
20 Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
21 Cc: Hugh Dickins <hughd@google.com>
22 Cc: James Hogan <james.hogan@imgtec.com>
23 Cc: David Rientjes <rientjes@google.com>
24 Cc: Mel Gorman <mel@csn.ul.ie>
25 Cc: Johannes Weiner <hannes@cmpxchg.org>
26 Cc: Michal Hocko <mhocko@suse.cz>
27 Cc: Rik van Riel <riel@redhat.com>
28 Cc: Andrea Arcangeli <aarcange@redhat.com>
29 Cc: Luiz Capitulino <lcapitulino@redhat.com>
30 Cc: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
31 Cc: Lee Schermerhorn <lee.schermerhorn@hp.com>
32 Cc: Steve Capper <steve.capper@linaro.org>
33 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
34 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
35 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
38 mm/hugetlb.c | 21 ++++++++++++++++++++-
39 1 file changed, 20 insertions(+), 1 deletion(-)
43 @@ -3384,7 +3384,26 @@ unsigned long hugetlb_change_protection(
47 - if (!huge_pte_none(huge_ptep_get(ptep))) {
48 + pte = huge_ptep_get(ptep);
49 + if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) {
53 + if (unlikely(is_hugetlb_entry_migration(pte))) {
54 + swp_entry_t entry = pte_to_swp_entry(pte);
56 + if (is_write_migration_entry(entry)) {
59 + make_migration_entry_read(&entry);
60 + newpte = swp_entry_to_pte(entry);
61 + set_huge_pte_at(mm, address, ptep, newpte);
67 + if (!huge_pte_none(pte)) {
68 pte = huge_ptep_get_and_clear(mm, address, ptep);
69 pte = pte_mkhuge(huge_pte_modify(pte, newprot));
70 pte = arch_make_huge_pte(pte, vma, NULL, 0);