aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/mm.h
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2014-02-13 07:53:33 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-02-21 02:50:21 -0500
commit634391ace193d00c59a691e9fc227b0f8942bad7 (patch)
treea78cb951b8cad9a3ea503677e6681c3b3f94d8b6 /include/linux/mm.h
parentdb85eaeb52637eb91a7bbc70f6684f5563b983e9 (diff)
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.h10
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)
1477 1477
1478#if USE_SPLIT_PMD_PTLOCKS 1478#if USE_SPLIT_PMD_PTLOCKS
1479 1479
1480static struct page *pmd_to_page(pmd_t *pmd)
1481{
1482 unsigned long mask = ~(PTRS_PER_PMD * sizeof(pmd_t) - 1);
1483 return virt_to_page((void *)((unsigned long) pmd & mask));
1484}
1485
1480static inline spinlock_t *pmd_lockptr(struct mm_struct *mm, pmd_t *pmd) 1486static inline spinlock_t *pmd_lockptr(struct mm_struct *mm, pmd_t *pmd)
1481{ 1487{
1482 return ptlock_ptr(virt_to_page(pmd)); 1488 return ptlock_ptr(pmd_to_page(pmd));
1483} 1489}
1484 1490
1485static inline bool pgtable_pmd_page_ctor(struct page *page) 1491static inline bool pgtable_pmd_page_ctor(struct page *page)
@@ -1498,7 +1504,7 @@ static inline void pgtable_pmd_page_dtor(struct page *page)
1498 ptlock_free(page); 1504 ptlock_free(page);
1499} 1505}
1500 1506
1501#define pmd_huge_pte(mm, pmd) (virt_to_page(pmd)->pmd_huge_pte) 1507#define pmd_huge_pte(mm, pmd) (pmd_to_page(pmd)->pmd_huge_pte)
1502 1508
1503#else 1509#else
1504 1510