]>
Commit | Line | Data |
---|---|---|
13a0632a GKH |
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 | |
5 | ||
6 | From: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | |
7 | ||
8 | commit a8bda28d87c38c6aa93de28ba5d30cc18e865a11 upstream. | |
9 | ||
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 | |
14 | problem. | |
15 | ||
16 | This patch adds is_hugetlb_entry_(migration|hwpoisoned) check in this | |
17 | function to do proper actions. | |
18 | ||
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> | |
36 | ||
37 | --- | |
38 | mm/hugetlb.c | 21 ++++++++++++++++++++- | |
39 | 1 file changed, 20 insertions(+), 1 deletion(-) | |
40 | ||
41 | --- a/mm/hugetlb.c | |
42 | +++ b/mm/hugetlb.c | |
43 | @@ -3384,7 +3384,26 @@ unsigned long hugetlb_change_protection( | |
44 | spin_unlock(ptl); | |
45 | continue; | |
46 | } | |
47 | - if (!huge_pte_none(huge_ptep_get(ptep))) { | |
48 | + pte = huge_ptep_get(ptep); | |
49 | + if (unlikely(is_hugetlb_entry_hwpoisoned(pte))) { | |
50 | + spin_unlock(ptl); | |
51 | + continue; | |
52 | + } | |
53 | + if (unlikely(is_hugetlb_entry_migration(pte))) { | |
54 | + swp_entry_t entry = pte_to_swp_entry(pte); | |
55 | + | |
56 | + if (is_write_migration_entry(entry)) { | |
57 | + pte_t newpte; | |
58 | + | |
59 | + make_migration_entry_read(&entry); | |
60 | + newpte = swp_entry_to_pte(entry); | |
61 | + set_huge_pte_at(mm, address, ptep, newpte); | |
62 | + pages++; | |
63 | + } | |
64 | + spin_unlock(ptl); | |
65 | + continue; | |
66 | + } | |
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); |