Skip to content

Commit 0979639

Browse files
Ross Zwislertorvalds
authored andcommitted
mm: add follow_pte_pmd()
Patch series "Write protect DAX PMDs in *sync path". Currently dax_mapping_entry_mkclean() fails to clean and write protect the pmd_t of a DAX PMD entry during an *sync operation. This can result in data loss, as detailed in patch 2. This series is based on Dan's "libnvdimm-pending" branch, which is the current home for Jan's "dax: Page invalidation fixes" series. You can find a working tree here: https://git.kernel.org/cgit/linux/kernel/git/zwisler/linux.git/log/?h=dax_pmd_clean This patch (of 2): Similar to follow_pte(), follow_pte_pmd() allows either a PTE leaf or a huge page PMD leaf to be found and returned. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ross Zwisler <[email protected]> Suggested-by: Dave Hansen <[email protected]> Cc: Alexander Viro <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Dan Williams <[email protected]> Cc: Dave Chinner <[email protected]> Cc: Jan Kara <[email protected]> Cc: Matthew Wilcox <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent d670ffd commit 0979639

File tree

2 files changed

+32
-7
lines changed

2 files changed

+32
-7
lines changed

include/linux/mm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,8 @@ void unmap_mapping_range(struct address_space *mapping,
12121212
loff_t const holebegin, loff_t const holelen, int even_cows);
12131213
int follow_pte(struct mm_struct *mm, unsigned long address, pte_t **ptepp,
12141214
spinlock_t **ptlp);
1215+
int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
1216+
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
12151217
int follow_pfn(struct vm_area_struct *vma, unsigned long address,
12161218
unsigned long *pfn);
12171219
int follow_phys(struct vm_area_struct *vma, unsigned long address,

mm/memory.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3772,8 +3772,8 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
37723772
}
37733773
#endif /* __PAGETABLE_PMD_FOLDED */
37743774

3775-
static int __follow_pte(struct mm_struct *mm, unsigned long address,
3776-
pte_t **ptepp, spinlock_t **ptlp)
3775+
static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
3776+
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
37773777
{
37783778
pgd_t *pgd;
37793779
pud_t *pud;
@@ -3790,11 +3790,20 @@ static int __follow_pte(struct mm_struct *mm, unsigned long address,
37903790

37913791
pmd = pmd_offset(pud, address);
37923792
VM_BUG_ON(pmd_trans_huge(*pmd));
3793-
if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
3794-
goto out;
37953793

3796-
/* We cannot handle huge page PFN maps. Luckily they don't exist. */
3797-
if (pmd_huge(*pmd))
3794+
if (pmd_huge(*pmd)) {
3795+
if (!pmdpp)
3796+
goto out;
3797+
3798+
*ptlp = pmd_lock(mm, pmd);
3799+
if (pmd_huge(*pmd)) {
3800+
*pmdpp = pmd;
3801+
return 0;
3802+
}
3803+
spin_unlock(*ptlp);
3804+
}
3805+
3806+
if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
37983807
goto out;
37993808

38003809
ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
@@ -3817,9 +3826,23 @@ int follow_pte(struct mm_struct *mm, unsigned long address, pte_t **ptepp,
38173826

38183827
/* (void) is needed to make gcc happy */
38193828
(void) __cond_lock(*ptlp,
3820-
!(res = __follow_pte(mm, address, ptepp, ptlp)));
3829+
!(res = __follow_pte_pmd(mm, address, ptepp, NULL,
3830+
ptlp)));
3831+
return res;
3832+
}
3833+
3834+
int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
3835+
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
3836+
{
3837+
int res;
3838+
3839+
/* (void) is needed to make gcc happy */
3840+
(void) __cond_lock(*ptlp,
3841+
!(res = __follow_pte_pmd(mm, address, ptepp, pmdpp,
3842+
ptlp)));
38213843
return res;
38223844
}
3845+
EXPORT_SYMBOL(follow_pte_pmd);
38233846

38243847
/**
38253848
* follow_pfn - look up PFN at a user virtual address

0 commit comments

Comments
 (0)