diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-06-08 19:19:40 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-06-08 19:19:40 +0200 |
commit | 987aec39a74373c55c3bedd5c3c83896d78fd0a2 (patch) | |
tree | 66aba6d4f166f269be95fe4d267d57efe533aefd /arch/powerpc/mm/hugetlbpage.c | |
parent | firmware: add missing kfree for work on async call (diff) | |
parent | Linux 4.1-rc7 (diff) | |
download | linux-987aec39a74373c55c3bedd5c3c83896d78fd0a2.tar.xz linux-987aec39a74373c55c3bedd5c3c83896d78fd0a2.zip |
Merge 4.1-rc7 into driver-core-next
We want the fixes in this branch as well for testing and merge
resolution.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/powerpc/mm/hugetlbpage.c')
-rw-r--r-- | arch/powerpc/mm/hugetlbpage.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index d230158c9770..6fd3fdeb1953 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -689,27 +689,34 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, struct page * follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) { - pte_t *ptep; - struct page *page; + pte_t *ptep, pte; unsigned shift; unsigned long mask, flags; + struct page *page = ERR_PTR(-EINVAL); + + local_irq_save(flags); + ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift); + if (!ptep) + goto no_page; + pte = READ_ONCE(*ptep); /* + * Verify it is a huge page else bail. * Transparent hugepages are handled by generic code. We can skip them * here. */ - local_irq_save(flags); - ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift); + if (!shift || pmd_trans_huge(__pmd(pte_val(pte)))) + goto no_page; - /* Verify it is a huge page else bail. */ - if (!ptep || !shift || pmd_trans_huge(*(pmd_t *)ptep)) { - local_irq_restore(flags); - return ERR_PTR(-EINVAL); + if (!pte_present(pte)) { + page = NULL; + goto no_page; } mask = (1UL << shift) - 1; - page = pte_page(*ptep); + page = pte_page(pte); if (page) page += (address & mask) / PAGE_SIZE; +no_page: local_irq_restore(flags); return page; } |