Skip to content

Commit a4d1a88

Browse files
Jérôme Glissetorvalds
authored andcommitted
dax: update to new mmu_notifier semantic
Replace all mmu_notifier_invalidate_page() calls by *_invalidate_range() and make sure it is bracketed by calls to *_invalidate_range_start()/end(). Note that because we can not presume the pmd value or pte value we have to assume the worst and unconditionaly report an invalidation as happening. Signed-off-by: Jérôme Glisse <[email protected]> Cc: Dan Williams <[email protected]> Cc: Ross Zwisler <[email protected]> Cc: Bernhard Held <[email protected]> Cc: Adam Borowski <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: Radim Krčmář <[email protected]> Cc: Wanpeng Li <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: Takashi Iwai <[email protected]> Cc: Nadav Amit <[email protected]> Cc: Mike Galbraith <[email protected]> Cc: Kirill A. Shutemov <[email protected]> Cc: axie <[email protected]> Cc: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 42ff72c commit a4d1a88

File tree

3 files changed

+33
-13
lines changed

3 files changed

+33
-13
lines changed

fs/dax.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -646,20 +646,24 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,
646646
pte_t pte, *ptep = NULL;
647647
pmd_t *pmdp = NULL;
648648
spinlock_t *ptl;
649-
bool changed;
650649

651650
i_mmap_lock_read(mapping);
652651
vma_interval_tree_foreach(vma, &mapping->i_mmap, index, index) {
653-
unsigned long address;
652+
unsigned long address, start, end;
654653

655654
cond_resched();
656655

657656
if (!(vma->vm_flags & VM_SHARED))
658657
continue;
659658

660659
address = pgoff_address(index, vma);
661-
changed = false;
662-
if (follow_pte_pmd(vma->vm_mm, address, &ptep, &pmdp, &ptl))
660+
661+
/*
662+
* Note because we provide start/end to follow_pte_pmd it will
663+
* call mmu_notifier_invalidate_range_start() on our behalf
664+
* before taking any lock.
665+
*/
666+
if (follow_pte_pmd(vma->vm_mm, address, &start, &end, &ptep, &pmdp, &ptl))
663667
continue;
664668

665669
if (pmdp) {
@@ -676,7 +680,7 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,
676680
pmd = pmd_wrprotect(pmd);
677681
pmd = pmd_mkclean(pmd);
678682
set_pmd_at(vma->vm_mm, address, pmdp, pmd);
679-
changed = true;
683+
mmu_notifier_invalidate_range(vma->vm_mm, start, end);
680684
unlock_pmd:
681685
spin_unlock(ptl);
682686
#endif
@@ -691,13 +695,12 @@ static void dax_mapping_entry_mkclean(struct address_space *mapping,
691695
pte = pte_wrprotect(pte);
692696
pte = pte_mkclean(pte);
693697
set_pte_at(vma->vm_mm, address, ptep, pte);
694-
changed = true;
698+
mmu_notifier_invalidate_range(vma->vm_mm, start, end);
695699
unlock_pte:
696700
pte_unmap_unlock(ptep, ptl);
697701
}
698702

699-
if (changed)
700-
mmu_notifier_invalidate_page(vma->vm_mm, address);
703+
mmu_notifier_invalidate_range_end(vma->vm_mm, start, end);
701704
}
702705
i_mmap_unlock_read(mapping);
703706
}

include/linux/mm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,7 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
12601260
void unmap_mapping_range(struct address_space *mapping,
12611261
loff_t const holebegin, loff_t const holelen, int even_cows);
12621262
int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
1263+
unsigned long *start, unsigned long *end,
12631264
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
12641265
int follow_pfn(struct vm_area_struct *vma, unsigned long address,
12651266
unsigned long *pfn);

mm/memory.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4008,7 +4008,8 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
40084008
#endif /* __PAGETABLE_PMD_FOLDED */
40094009

40104010
static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
4011-
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
4011+
unsigned long *start, unsigned long *end,
4012+
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
40124013
{
40134014
pgd_t *pgd;
40144015
p4d_t *p4d;
@@ -4035,24 +4036,38 @@ static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
40354036
if (!pmdpp)
40364037
goto out;
40374038

4039+
if (start && end) {
4040+
*start = address & PMD_MASK;
4041+
*end = *start + PMD_SIZE;
4042+
mmu_notifier_invalidate_range_start(mm, *start, *end);
4043+
}
40384044
*ptlp = pmd_lock(mm, pmd);
40394045
if (pmd_huge(*pmd)) {
40404046
*pmdpp = pmd;
40414047
return 0;
40424048
}
40434049
spin_unlock(*ptlp);
4050+
if (start && end)
4051+
mmu_notifier_invalidate_range_end(mm, *start, *end);
40444052
}
40454053

40464054
if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
40474055
goto out;
40484056

4057+
if (start && end) {
4058+
*start = address & PAGE_MASK;
4059+
*end = *start + PAGE_SIZE;
4060+
mmu_notifier_invalidate_range_start(mm, *start, *end);
4061+
}
40494062
ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
40504063
if (!pte_present(*ptep))
40514064
goto unlock;
40524065
*ptepp = ptep;
40534066
return 0;
40544067
unlock:
40554068
pte_unmap_unlock(ptep, *ptlp);
4069+
if (start && end)
4070+
mmu_notifier_invalidate_range_end(mm, *start, *end);
40564071
out:
40574072
return -EINVAL;
40584073
}
@@ -4064,20 +4079,21 @@ static inline int follow_pte(struct mm_struct *mm, unsigned long address,
40644079

40654080
/* (void) is needed to make gcc happy */
40664081
(void) __cond_lock(*ptlp,
4067-
!(res = __follow_pte_pmd(mm, address, ptepp, NULL,
4068-
ptlp)));
4082+
!(res = __follow_pte_pmd(mm, address, NULL, NULL,
4083+
ptepp, NULL, ptlp)));
40694084
return res;
40704085
}
40714086

40724087
int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
4088+
unsigned long *start, unsigned long *end,
40734089
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
40744090
{
40754091
int res;
40764092

40774093
/* (void) is needed to make gcc happy */
40784094
(void) __cond_lock(*ptlp,
4079-
!(res = __follow_pte_pmd(mm, address, ptepp, pmdpp,
4080-
ptlp)));
4095+
!(res = __follow_pte_pmd(mm, address, start, end,
4096+
ptepp, pmdpp, ptlp)));
40814097
return res;
40824098
}
40834099
EXPORT_SYMBOL(follow_pte_pmd);

0 commit comments

Comments
 (0)