diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2014-02-13 13:53:33 +0100 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2014-02-21 08:50:21 +0100 |
commit | 634391ace193d00c59a691e9fc227b0f8942bad7 (patch) | |
tree | a78cb951b8cad9a3ea503677e6681c3b3f94d8b6 /include/linux/mm.h | |
parent | db85eaeb52637eb91a7bbc70f6684f5563b983e9 (diff) | |
download | linux-634391ace193d00c59a691e9fc227b0f8942bad7.tar.gz linux-634391ace193d00c59a691e9fc227b0f8942bad7.tar.bz2 linux-634391ace193d00c59a691e9fc227b0f8942bad7.zip |
mm: mask bits from pmd in pmd_lockptr/pmd_huge_pte
The pmd pointer passed to pmd_lockptr/pmd_huge_pte can point to any
entry in a pmd table. With USE_SPLIT_PMD_PTLOCKS==1 the code uses
virt_to_page to get a struct page for the pmd table. The virt_to_page
function automatically masks the lower PAGE_SHIFT bits from the
address. But if the size of a pmd table is larger than PAGE_SIZE the
additional bits are not removed from the pmd address and the wrong
page struct is used.
Fix this by explicitely masking the offset in the pmd table from
the pmd pointer.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'include/linux/mm.h')
-rw-r--r-- | include/linux/mm.h | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index f28f46eade6a..d354a72e6127 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1477,9 +1477,15 @@ static inline void pgtable_page_dtor(struct page *page) #if USE_SPLIT_PMD_PTLOCKS +static struct page *pmd_to_page(pmd_t *pmd) +{ + unsigned long mask = ~(PTRS_PER_PMD * sizeof(pmd_t) - 1); + return virt_to_page((void *)((unsigned long) pmd & mask)); +} + static inline spinlock_t *pmd_lockptr(struct mm_struct *mm, pmd_t *pmd) { - return ptlock_ptr(virt_to_page(pmd)); + return ptlock_ptr(pmd_to_page(pmd)); } static inline bool pgtable_pmd_page_ctor(struct page *page) @@ -1498,7 +1504,7 @@ static inline void pgtable_pmd_page_dtor(struct page *page) ptlock_free(page); } -#define pmd_huge_pte(mm, pmd) (virt_to_page(pmd)->pmd_huge_pte) +#define pmd_huge_pte(mm, pmd) (pmd_to_page(pmd)->pmd_huge_pte) #else |