diff options
author | Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | 2014-04-23 08:27:05 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2014-04-23 08:27:05 +1000 |
commit | d7bcf989a04ef2f8918f5745a79551953369a42e (patch) | |
tree | 4973b08a73c080a64c8d6a290af682427fc15415 /mm/mempolicy.c | |
parent | fe5d4a685d60cfc331039b2451bd96e4f959a1cb (diff) |
mm: add !pte_present() check on existing hugetlb_entry callbacks
Page table walker doesn't check non-present hugetlb entry in common path,
so hugetlb_entry() callbacks must check it. The reason for this behavior
is that some callers want to handle it in its own way.
However, some callers don't check it now, which causes unpredictable
result, for example when we have a race between migrating hugepage and
reading /proc/pid/numa_maps. This patch fixes it by adding !pte_present
checks on buggy callbacks.
This bug exists for years and got visible by introducing hugepage migration.
ChangeLog v2:
- fix if condition (check !pte_present() instead of pte_present())
Reported-by: Sasha Levin <sasha.levin@oracle.com>
Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: <stable@vger.kernel.org> [3.12+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index af635c458dee..9d2ef4111a4c 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -524,8 +524,12 @@ static int queue_pages_hugetlb(pte_t *pte, unsigned long addr, unsigned long flags = qp->flags; int nid; struct page *page; + pte_t entry; - page = pte_page(huge_ptep_get(pte)); + entry = huge_ptep_get(pte); + if (!pte_present(entry)) + return 0; + page = pte_page(entry); nid = page_to_nid(page); if (node_isset(nid, *qp->nmask) == !!(flags & MPOL_MF_INVERT)) return 0; |