diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/filemap_xip.c | 4 | ||||
-rw-r--r-- | mm/huge_memory.c | 42 | ||||
-rw-r--r-- | mm/hugetlb.c | 21 | ||||
-rw-r--r-- | mm/memory.c | 28 | ||||
-rw-r--r-- | mm/mremap.c | 8 | ||||
-rw-r--r-- | mm/rmap.c | 18 |
6 files changed, 92 insertions, 29 deletions
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index a52daee11d3f..a912da6ddfd4 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c | |||
@@ -192,11 +192,13 @@ retry: | |||
192 | if (pte) { | 192 | if (pte) { |
193 | /* Nuke the page table entry. */ | 193 | /* Nuke the page table entry. */ |
194 | flush_cache_page(vma, address, pte_pfn(*pte)); | 194 | flush_cache_page(vma, address, pte_pfn(*pte)); |
195 | pteval = ptep_clear_flush_notify(vma, address, pte); | 195 | pteval = ptep_clear_flush(vma, address, pte); |
196 | page_remove_rmap(page); | 196 | page_remove_rmap(page); |
197 | dec_mm_counter(mm, MM_FILEPAGES); | 197 | dec_mm_counter(mm, MM_FILEPAGES); |
198 | BUG_ON(pte_dirty(pteval)); | 198 | BUG_ON(pte_dirty(pteval)); |
199 | pte_unmap_unlock(pte, ptl); | 199 | pte_unmap_unlock(pte, ptl); |
200 | /* must invalidate_page _before_ freeing the page */ | ||
201 | mmu_notifier_invalidate_page(mm, address); | ||
200 | page_cache_release(page); | 202 | page_cache_release(page); |
201 | } | 203 | } |
202 | } | 204 | } |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 0e7740923fb9..08a943b9cf95 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -787,6 +787,8 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, | |||
787 | pmd_t _pmd; | 787 | pmd_t _pmd; |
788 | int ret = 0, i; | 788 | int ret = 0, i; |
789 | struct page **pages; | 789 | struct page **pages; |
790 | unsigned long mmun_start; /* For mmu_notifiers */ | ||
791 | unsigned long mmun_end; /* For mmu_notifiers */ | ||
790 | 792 | ||
791 | pages = kmalloc(sizeof(struct page *) * HPAGE_PMD_NR, | 793 | pages = kmalloc(sizeof(struct page *) * HPAGE_PMD_NR, |
792 | GFP_KERNEL); | 794 | GFP_KERNEL); |
@@ -823,12 +825,16 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, | |||
823 | cond_resched(); | 825 | cond_resched(); |
824 | } | 826 | } |
825 | 827 | ||
828 | mmun_start = haddr; | ||
829 | mmun_end = haddr + HPAGE_PMD_SIZE; | ||
830 | mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); | ||
831 | |||
826 | spin_lock(&mm->page_table_lock); | 832 | spin_lock(&mm->page_table_lock); |
827 | if (unlikely(!pmd_same(*pmd, orig_pmd))) | 833 | if (unlikely(!pmd_same(*pmd, orig_pmd))) |
828 | goto out_free_pages; | 834 | goto out_free_pages; |
829 | VM_BUG_ON(!PageHead(page)); | 835 | VM_BUG_ON(!PageHead(page)); |
830 | 836 | ||
831 | pmdp_clear_flush_notify(vma, haddr, pmd); | 837 | pmdp_clear_flush(vma, haddr, pmd); |
832 | /* leave pmd empty until pte is filled */ | 838 | /* leave pmd empty until pte is filled */ |
833 | 839 | ||
834 | pgtable = pgtable_trans_huge_withdraw(mm); | 840 | pgtable = pgtable_trans_huge_withdraw(mm); |
@@ -851,6 +857,8 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, | |||
851 | page_remove_rmap(page); | 857 | page_remove_rmap(page); |
852 | spin_unlock(&mm->page_table_lock); | 858 | spin_unlock(&mm->page_table_lock); |
853 | 859 | ||
860 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | ||
861 | |||
854 | ret |= VM_FAULT_WRITE; | 862 | ret |= VM_FAULT_WRITE; |
855 | put_page(page); | 863 | put_page(page); |
856 | 864 | ||
@@ -859,6 +867,7 @@ out: | |||
859 | 867 | ||
860 | out_free_pages: | 868 | out_free_pages: |
861 | spin_unlock(&mm->page_table_lock); | 869 | spin_unlock(&mm->page_table_lock); |
870 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | ||
862 | mem_cgroup_uncharge_start(); | 871 | mem_cgroup_uncharge_start(); |
863 | for (i = 0; i < HPAGE_PMD_NR; i++) { | 872 | for (i = 0; i < HPAGE_PMD_NR; i++) { |
864 | mem_cgroup_uncharge_page(pages[i]); | 873 | mem_cgroup_uncharge_page(pages[i]); |
@@ -875,6 +884,8 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
875 | int ret = 0; | 884 | int ret = 0; |
876 | struct page *page, *new_page; | 885 | struct page *page, *new_page; |
877 | unsigned long haddr; | 886 | unsigned long haddr; |
887 | unsigned long mmun_start; /* For mmu_notifiers */ | ||
888 | unsigned long mmun_end; /* For mmu_notifiers */ | ||
878 | 889 | ||
879 | VM_BUG_ON(!vma->anon_vma); | 890 | VM_BUG_ON(!vma->anon_vma); |
880 | spin_lock(&mm->page_table_lock); | 891 | spin_lock(&mm->page_table_lock); |
@@ -925,20 +936,24 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
925 | copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR); | 936 | copy_user_huge_page(new_page, page, haddr, vma, HPAGE_PMD_NR); |
926 | __SetPageUptodate(new_page); | 937 | __SetPageUptodate(new_page); |
927 | 938 | ||
939 | mmun_start = haddr; | ||
940 | mmun_end = haddr + HPAGE_PMD_SIZE; | ||
941 | mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); | ||
942 | |||
928 | spin_lock(&mm->page_table_lock); | 943 | spin_lock(&mm->page_table_lock); |
929 | put_page(page); | 944 | put_page(page); |
930 | if (unlikely(!pmd_same(*pmd, orig_pmd))) { | 945 | if (unlikely(!pmd_same(*pmd, orig_pmd))) { |
931 | spin_unlock(&mm->page_table_lock); | 946 | spin_unlock(&mm->page_table_lock); |
932 | mem_cgroup_uncharge_page(new_page); | 947 | mem_cgroup_uncharge_page(new_page); |
933 | put_page(new_page); | 948 | put_page(new_page); |
934 | goto out; | 949 | goto out_mn; |
935 | } else { | 950 | } else { |
936 | pmd_t entry; | 951 | pmd_t entry; |
937 | VM_BUG_ON(!PageHead(page)); | 952 | VM_BUG_ON(!PageHead(page)); |
938 | entry = mk_pmd(new_page, vma->vm_page_prot); | 953 | entry = mk_pmd(new_page, vma->vm_page_prot); |
939 | entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); | 954 | entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma); |
940 | entry = pmd_mkhuge(entry); | 955 | entry = pmd_mkhuge(entry); |
941 | pmdp_clear_flush_notify(vma, haddr, pmd); | 956 | pmdp_clear_flush(vma, haddr, pmd); |
942 | page_add_new_anon_rmap(new_page, vma, haddr); | 957 | page_add_new_anon_rmap(new_page, vma, haddr); |
943 | set_pmd_at(mm, haddr, pmd, entry); | 958 | set_pmd_at(mm, haddr, pmd, entry); |
944 | update_mmu_cache(vma, address, pmd); | 959 | update_mmu_cache(vma, address, pmd); |
@@ -946,10 +961,14 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
946 | put_page(page); | 961 | put_page(page); |
947 | ret |= VM_FAULT_WRITE; | 962 | ret |= VM_FAULT_WRITE; |
948 | } | 963 | } |
949 | out_unlock: | ||
950 | spin_unlock(&mm->page_table_lock); | 964 | spin_unlock(&mm->page_table_lock); |
965 | out_mn: | ||
966 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | ||
951 | out: | 967 | out: |
952 | return ret; | 968 | return ret; |
969 | out_unlock: | ||
970 | spin_unlock(&mm->page_table_lock); | ||
971 | return ret; | ||
953 | } | 972 | } |
954 | 973 | ||
955 | struct page *follow_trans_huge_pmd(struct mm_struct *mm, | 974 | struct page *follow_trans_huge_pmd(struct mm_struct *mm, |
@@ -1162,7 +1181,11 @@ static int __split_huge_page_splitting(struct page *page, | |||
1162 | struct mm_struct *mm = vma->vm_mm; | 1181 | struct mm_struct *mm = vma->vm_mm; |
1163 | pmd_t *pmd; | 1182 | pmd_t *pmd; |
1164 | int ret = 0; | 1183 | int ret = 0; |
1184 | /* For mmu_notifiers */ | ||
1185 | const unsigned long mmun_start = address; | ||
1186 | const unsigned long mmun_end = address + HPAGE_PMD_SIZE; | ||
1165 | 1187 | ||
1188 | mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); | ||
1166 | spin_lock(&mm->page_table_lock); | 1189 | spin_lock(&mm->page_table_lock); |
1167 | pmd = page_check_address_pmd(page, mm, address, | 1190 | pmd = page_check_address_pmd(page, mm, address, |
1168 | PAGE_CHECK_ADDRESS_PMD_NOTSPLITTING_FLAG); | 1191 | PAGE_CHECK_ADDRESS_PMD_NOTSPLITTING_FLAG); |
@@ -1174,10 +1197,11 @@ static int __split_huge_page_splitting(struct page *page, | |||
1174 | * and it won't wait on the anon_vma->root->mutex to | 1197 | * and it won't wait on the anon_vma->root->mutex to |
1175 | * serialize against split_huge_page*. | 1198 | * serialize against split_huge_page*. |
1176 | */ | 1199 | */ |
1177 | pmdp_splitting_flush_notify(vma, address, pmd); | 1200 | pmdp_splitting_flush(vma, address, pmd); |
1178 | ret = 1; | 1201 | ret = 1; |
1179 | } | 1202 | } |
1180 | spin_unlock(&mm->page_table_lock); | 1203 | spin_unlock(&mm->page_table_lock); |
1204 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | ||
1181 | 1205 | ||
1182 | return ret; | 1206 | return ret; |
1183 | } | 1207 | } |
@@ -1898,6 +1922,8 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
1898 | spinlock_t *ptl; | 1922 | spinlock_t *ptl; |
1899 | int isolated; | 1923 | int isolated; |
1900 | unsigned long hstart, hend; | 1924 | unsigned long hstart, hend; |
1925 | unsigned long mmun_start; /* For mmu_notifiers */ | ||
1926 | unsigned long mmun_end; /* For mmu_notifiers */ | ||
1901 | 1927 | ||
1902 | VM_BUG_ON(address & ~HPAGE_PMD_MASK); | 1928 | VM_BUG_ON(address & ~HPAGE_PMD_MASK); |
1903 | 1929 | ||
@@ -1952,6 +1978,9 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
1952 | pte = pte_offset_map(pmd, address); | 1978 | pte = pte_offset_map(pmd, address); |
1953 | ptl = pte_lockptr(mm, pmd); | 1979 | ptl = pte_lockptr(mm, pmd); |
1954 | 1980 | ||
1981 | mmun_start = address; | ||
1982 | mmun_end = address + HPAGE_PMD_SIZE; | ||
1983 | mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); | ||
1955 | spin_lock(&mm->page_table_lock); /* probably unnecessary */ | 1984 | spin_lock(&mm->page_table_lock); /* probably unnecessary */ |
1956 | /* | 1985 | /* |
1957 | * After this gup_fast can't run anymore. This also removes | 1986 | * After this gup_fast can't run anymore. This also removes |
@@ -1959,8 +1988,9 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
1959 | * huge and small TLB entries for the same virtual address | 1988 | * huge and small TLB entries for the same virtual address |
1960 | * to avoid the risk of CPU bugs in that area. | 1989 | * to avoid the risk of CPU bugs in that area. |
1961 | */ | 1990 | */ |
1962 | _pmd = pmdp_clear_flush_notify(vma, address, pmd); | 1991 | _pmd = pmdp_clear_flush(vma, address, pmd); |
1963 | spin_unlock(&mm->page_table_lock); | 1992 | spin_unlock(&mm->page_table_lock); |
1993 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | ||
1964 | 1994 | ||
1965 | spin_lock(ptl); | 1995 | spin_lock(ptl); |
1966 | isolated = __collapse_huge_page_isolate(vma, address, pte); | 1996 | isolated = __collapse_huge_page_isolate(vma, address, pte); |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index de5d1dcf34fe..993f7c1820a8 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -2355,13 +2355,15 @@ void __unmap_hugepage_range(struct mmu_gather *tlb, struct vm_area_struct *vma, | |||
2355 | struct page *page; | 2355 | struct page *page; |
2356 | struct hstate *h = hstate_vma(vma); | 2356 | struct hstate *h = hstate_vma(vma); |
2357 | unsigned long sz = huge_page_size(h); | 2357 | unsigned long sz = huge_page_size(h); |
2358 | const unsigned long mmun_start = start; /* For mmu_notifiers */ | ||
2359 | const unsigned long mmun_end = end; /* For mmu_notifiers */ | ||
2358 | 2360 | ||
2359 | WARN_ON(!is_vm_hugetlb_page(vma)); | 2361 | WARN_ON(!is_vm_hugetlb_page(vma)); |
2360 | BUG_ON(start & ~huge_page_mask(h)); | 2362 | BUG_ON(start & ~huge_page_mask(h)); |
2361 | BUG_ON(end & ~huge_page_mask(h)); | 2363 | BUG_ON(end & ~huge_page_mask(h)); |
2362 | 2364 | ||
2363 | tlb_start_vma(tlb, vma); | 2365 | tlb_start_vma(tlb, vma); |
2364 | mmu_notifier_invalidate_range_start(mm, start, end); | 2366 | mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); |
2365 | again: | 2367 | again: |
2366 | spin_lock(&mm->page_table_lock); | 2368 | spin_lock(&mm->page_table_lock); |
2367 | for (address = start; address < end; address += sz) { | 2369 | for (address = start; address < end; address += sz) { |
@@ -2425,7 +2427,7 @@ again: | |||
2425 | if (address < end && !ref_page) | 2427 | if (address < end && !ref_page) |
2426 | goto again; | 2428 | goto again; |
2427 | } | 2429 | } |
2428 | mmu_notifier_invalidate_range_end(mm, start, end); | 2430 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); |
2429 | tlb_end_vma(tlb, vma); | 2431 | tlb_end_vma(tlb, vma); |
2430 | } | 2432 | } |
2431 | 2433 | ||
@@ -2525,6 +2527,8 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2525 | struct page *old_page, *new_page; | 2527 | struct page *old_page, *new_page; |
2526 | int avoidcopy; | 2528 | int avoidcopy; |
2527 | int outside_reserve = 0; | 2529 | int outside_reserve = 0; |
2530 | unsigned long mmun_start; /* For mmu_notifiers */ | ||
2531 | unsigned long mmun_end; /* For mmu_notifiers */ | ||
2528 | 2532 | ||
2529 | old_page = pte_page(pte); | 2533 | old_page = pte_page(pte); |
2530 | 2534 | ||
@@ -2611,6 +2615,9 @@ retry_avoidcopy: | |||
2611 | pages_per_huge_page(h)); | 2615 | pages_per_huge_page(h)); |
2612 | __SetPageUptodate(new_page); | 2616 | __SetPageUptodate(new_page); |
2613 | 2617 | ||
2618 | mmun_start = address & huge_page_mask(h); | ||
2619 | mmun_end = mmun_start + huge_page_size(h); | ||
2620 | mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); | ||
2614 | /* | 2621 | /* |
2615 | * Retake the page_table_lock to check for racing updates | 2622 | * Retake the page_table_lock to check for racing updates |
2616 | * before the page tables are altered | 2623 | * before the page tables are altered |
@@ -2619,9 +2626,6 @@ retry_avoidcopy: | |||
2619 | ptep = huge_pte_offset(mm, address & huge_page_mask(h)); | 2626 | ptep = huge_pte_offset(mm, address & huge_page_mask(h)); |
2620 | if (likely(pte_same(huge_ptep_get(ptep), pte))) { | 2627 | if (likely(pte_same(huge_ptep_get(ptep), pte))) { |
2621 | /* Break COW */ | 2628 | /* Break COW */ |
2622 | mmu_notifier_invalidate_range_start(mm, | ||
2623 | address & huge_page_mask(h), | ||
2624 | (address & huge_page_mask(h)) + huge_page_size(h)); | ||
2625 | huge_ptep_clear_flush(vma, address, ptep); | 2629 | huge_ptep_clear_flush(vma, address, ptep); |
2626 | set_huge_pte_at(mm, address, ptep, | 2630 | set_huge_pte_at(mm, address, ptep, |
2627 | make_huge_pte(vma, new_page, 1)); | 2631 | make_huge_pte(vma, new_page, 1)); |
@@ -2629,10 +2633,11 @@ retry_avoidcopy: | |||
2629 | hugepage_add_new_anon_rmap(new_page, vma, address); | 2633 | hugepage_add_new_anon_rmap(new_page, vma, address); |
2630 | /* Make the old page be freed below */ | 2634 | /* Make the old page be freed below */ |
2631 | new_page = old_page; | 2635 | new_page = old_page; |
2632 | mmu_notifier_invalidate_range_end(mm, | ||
2633 | address & huge_page_mask(h), | ||
2634 | (address & huge_page_mask(h)) + huge_page_size(h)); | ||
2635 | } | 2636 | } |
2637 | spin_unlock(&mm->page_table_lock); | ||
2638 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | ||
2639 | /* Caller expects lock to be held */ | ||
2640 | spin_lock(&mm->page_table_lock); | ||
2636 | page_cache_release(new_page); | 2641 | page_cache_release(new_page); |
2637 | page_cache_release(old_page); | 2642 | page_cache_release(old_page); |
2638 | return 0; | 2643 | return 0; |
diff --git a/mm/memory.c b/mm/memory.c index 5f5d1f039bf4..b03a4a21c1d0 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -712,7 +712,7 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr, | |||
712 | add_taint(TAINT_BAD_PAGE); | 712 | add_taint(TAINT_BAD_PAGE); |
713 | } | 713 | } |
714 | 714 | ||
715 | static inline int is_cow_mapping(vm_flags_t flags) | 715 | static inline bool is_cow_mapping(vm_flags_t flags) |
716 | { | 716 | { |
717 | return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE; | 717 | return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE; |
718 | } | 718 | } |
@@ -1039,6 +1039,9 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
1039 | unsigned long next; | 1039 | unsigned long next; |
1040 | unsigned long addr = vma->vm_start; | 1040 | unsigned long addr = vma->vm_start; |
1041 | unsigned long end = vma->vm_end; | 1041 | unsigned long end = vma->vm_end; |
1042 | unsigned long mmun_start; /* For mmu_notifiers */ | ||
1043 | unsigned long mmun_end; /* For mmu_notifiers */ | ||
1044 | bool is_cow; | ||
1042 | int ret; | 1045 | int ret; |
1043 | 1046 | ||
1044 | /* | 1047 | /* |
@@ -1072,8 +1075,12 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
1072 | * parent mm. And a permission downgrade will only happen if | 1075 | * parent mm. And a permission downgrade will only happen if |
1073 | * is_cow_mapping() returns true. | 1076 | * is_cow_mapping() returns true. |
1074 | */ | 1077 | */ |
1075 | if (is_cow_mapping(vma->vm_flags)) | 1078 | is_cow = is_cow_mapping(vma->vm_flags); |
1076 | mmu_notifier_invalidate_range_start(src_mm, addr, end); | 1079 | mmun_start = addr; |
1080 | mmun_end = end; | ||
1081 | if (is_cow) | ||
1082 | mmu_notifier_invalidate_range_start(src_mm, mmun_start, | ||
1083 | mmun_end); | ||
1077 | 1084 | ||
1078 | ret = 0; | 1085 | ret = 0; |
1079 | dst_pgd = pgd_offset(dst_mm, addr); | 1086 | dst_pgd = pgd_offset(dst_mm, addr); |
@@ -1089,9 +1096,8 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm, | |||
1089 | } | 1096 | } |
1090 | } while (dst_pgd++, src_pgd++, addr = next, addr != end); | 1097 | } while (dst_pgd++, src_pgd++, addr = next, addr != end); |
1091 | 1098 | ||
1092 | if (is_cow_mapping(vma->vm_flags)) | 1099 | if (is_cow) |
1093 | mmu_notifier_invalidate_range_end(src_mm, | 1100 | mmu_notifier_invalidate_range_end(src_mm, mmun_start, mmun_end); |
1094 | vma->vm_start, end); | ||
1095 | return ret; | 1101 | return ret; |
1096 | } | 1102 | } |
1097 | 1103 | ||
@@ -2516,7 +2522,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2516 | spinlock_t *ptl, pte_t orig_pte) | 2522 | spinlock_t *ptl, pte_t orig_pte) |
2517 | __releases(ptl) | 2523 | __releases(ptl) |
2518 | { | 2524 | { |
2519 | struct page *old_page, *new_page; | 2525 | struct page *old_page, *new_page = NULL; |
2520 | pte_t entry; | 2526 | pte_t entry; |
2521 | int ret = 0; | 2527 | int ret = 0; |
2522 | int page_mkwrite = 0; | 2528 | int page_mkwrite = 0; |
@@ -2760,10 +2766,14 @@ gotten: | |||
2760 | } else | 2766 | } else |
2761 | mem_cgroup_uncharge_page(new_page); | 2767 | mem_cgroup_uncharge_page(new_page); |
2762 | 2768 | ||
2763 | if (new_page) | ||
2764 | page_cache_release(new_page); | ||
2765 | unlock: | 2769 | unlock: |
2766 | pte_unmap_unlock(page_table, ptl); | 2770 | pte_unmap_unlock(page_table, ptl); |
2771 | if (new_page) { | ||
2772 | if (new_page == old_page) | ||
2773 | /* cow happened, notify before releasing old_page */ | ||
2774 | mmu_notifier_invalidate_page(mm, address); | ||
2775 | page_cache_release(new_page); | ||
2776 | } | ||
2767 | if (old_page) { | 2777 | if (old_page) { |
2768 | /* | 2778 | /* |
2769 | * Don't let another task, with possibly unlocked vma, | 2779 | * Don't let another task, with possibly unlocked vma, |
diff --git a/mm/mremap.c b/mm/mremap.c index 3b639a4b26bd..1b61c2d3307a 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
@@ -149,11 +149,15 @@ unsigned long move_page_tables(struct vm_area_struct *vma, | |||
149 | unsigned long extent, next, old_end; | 149 | unsigned long extent, next, old_end; |
150 | pmd_t *old_pmd, *new_pmd; | 150 | pmd_t *old_pmd, *new_pmd; |
151 | bool need_flush = false; | 151 | bool need_flush = false; |
152 | unsigned long mmun_start; /* For mmu_notifiers */ | ||
153 | unsigned long mmun_end; /* For mmu_notifiers */ | ||
152 | 154 | ||
153 | old_end = old_addr + len; | 155 | old_end = old_addr + len; |
154 | flush_cache_range(vma, old_addr, old_end); | 156 | flush_cache_range(vma, old_addr, old_end); |
155 | 157 | ||
156 | mmu_notifier_invalidate_range_start(vma->vm_mm, old_addr, old_end); | 158 | mmun_start = old_addr; |
159 | mmun_end = old_end; | ||
160 | mmu_notifier_invalidate_range_start(vma->vm_mm, mmun_start, mmun_end); | ||
157 | 161 | ||
158 | for (; old_addr < old_end; old_addr += extent, new_addr += extent) { | 162 | for (; old_addr < old_end; old_addr += extent, new_addr += extent) { |
159 | cond_resched(); | 163 | cond_resched(); |
@@ -197,7 +201,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma, | |||
197 | if (likely(need_flush)) | 201 | if (likely(need_flush)) |
198 | flush_tlb_range(vma, old_end-len, old_addr); | 202 | flush_tlb_range(vma, old_end-len, old_addr); |
199 | 203 | ||
200 | mmu_notifier_invalidate_range_end(vma->vm_mm, old_end-len, old_end); | 204 | mmu_notifier_invalidate_range_end(vma->vm_mm, mmun_start, mmun_end); |
201 | 205 | ||
202 | return len + old_addr - old_end; /* how much done */ | 206 | return len + old_addr - old_end; /* how much done */ |
203 | } | 207 | } |
@@ -884,7 +884,7 @@ static int page_mkclean_one(struct page *page, struct vm_area_struct *vma, | |||
884 | pte_t entry; | 884 | pte_t entry; |
885 | 885 | ||
886 | flush_cache_page(vma, address, pte_pfn(*pte)); | 886 | flush_cache_page(vma, address, pte_pfn(*pte)); |
887 | entry = ptep_clear_flush_notify(vma, address, pte); | 887 | entry = ptep_clear_flush(vma, address, pte); |
888 | entry = pte_wrprotect(entry); | 888 | entry = pte_wrprotect(entry); |
889 | entry = pte_mkclean(entry); | 889 | entry = pte_mkclean(entry); |
890 | set_pte_at(mm, address, pte, entry); | 890 | set_pte_at(mm, address, pte, entry); |
@@ -892,6 +892,9 @@ static int page_mkclean_one(struct page *page, struct vm_area_struct *vma, | |||
892 | } | 892 | } |
893 | 893 | ||
894 | pte_unmap_unlock(pte, ptl); | 894 | pte_unmap_unlock(pte, ptl); |
895 | |||
896 | if (ret) | ||
897 | mmu_notifier_invalidate_page(mm, address); | ||
895 | out: | 898 | out: |
896 | return ret; | 899 | return ret; |
897 | } | 900 | } |
@@ -1212,7 +1215,7 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
1212 | 1215 | ||
1213 | /* Nuke the page table entry. */ | 1216 | /* Nuke the page table entry. */ |
1214 | flush_cache_page(vma, address, page_to_pfn(page)); | 1217 | flush_cache_page(vma, address, page_to_pfn(page)); |
1215 | pteval = ptep_clear_flush_notify(vma, address, pte); | 1218 | pteval = ptep_clear_flush(vma, address, pte); |
1216 | 1219 | ||
1217 | /* Move the dirty bit to the physical page now the pte is gone. */ | 1220 | /* Move the dirty bit to the physical page now the pte is gone. */ |
1218 | if (pte_dirty(pteval)) | 1221 | if (pte_dirty(pteval)) |
@@ -1274,6 +1277,8 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma, | |||
1274 | 1277 | ||
1275 | out_unmap: | 1278 | out_unmap: |
1276 | pte_unmap_unlock(pte, ptl); | 1279 | pte_unmap_unlock(pte, ptl); |
1280 | if (ret != SWAP_FAIL) | ||
1281 | mmu_notifier_invalidate_page(mm, address); | ||
1277 | out: | 1282 | out: |
1278 | return ret; | 1283 | return ret; |
1279 | 1284 | ||
@@ -1338,6 +1343,8 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount, | |||
1338 | spinlock_t *ptl; | 1343 | spinlock_t *ptl; |
1339 | struct page *page; | 1344 | struct page *page; |
1340 | unsigned long address; | 1345 | unsigned long address; |
1346 | unsigned long mmun_start; /* For mmu_notifiers */ | ||
1347 | unsigned long mmun_end; /* For mmu_notifiers */ | ||
1341 | unsigned long end; | 1348 | unsigned long end; |
1342 | int ret = SWAP_AGAIN; | 1349 | int ret = SWAP_AGAIN; |
1343 | int locked_vma = 0; | 1350 | int locked_vma = 0; |
@@ -1361,6 +1368,10 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount, | |||
1361 | if (!pmd_present(*pmd)) | 1368 | if (!pmd_present(*pmd)) |
1362 | return ret; | 1369 | return ret; |
1363 | 1370 | ||
1371 | mmun_start = address; | ||
1372 | mmun_end = end; | ||
1373 | mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end); | ||
1374 | |||
1364 | /* | 1375 | /* |
1365 | * If we can acquire the mmap_sem for read, and vma is VM_LOCKED, | 1376 | * If we can acquire the mmap_sem for read, and vma is VM_LOCKED, |
1366 | * keep the sem while scanning the cluster for mlocking pages. | 1377 | * keep the sem while scanning the cluster for mlocking pages. |
@@ -1394,7 +1405,7 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount, | |||
1394 | 1405 | ||
1395 | /* Nuke the page table entry. */ | 1406 | /* Nuke the page table entry. */ |
1396 | flush_cache_page(vma, address, pte_pfn(*pte)); | 1407 | flush_cache_page(vma, address, pte_pfn(*pte)); |
1397 | pteval = ptep_clear_flush_notify(vma, address, pte); | 1408 | pteval = ptep_clear_flush(vma, address, pte); |
1398 | 1409 | ||
1399 | /* If nonlinear, store the file page offset in the pte. */ | 1410 | /* If nonlinear, store the file page offset in the pte. */ |
1400 | if (page->index != linear_page_index(vma, address)) | 1411 | if (page->index != linear_page_index(vma, address)) |
@@ -1410,6 +1421,7 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount, | |||
1410 | (*mapcount)--; | 1421 | (*mapcount)--; |
1411 | } | 1422 | } |
1412 | pte_unmap_unlock(pte - 1, ptl); | 1423 | pte_unmap_unlock(pte - 1, ptl); |
1424 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | ||
1413 | if (locked_vma) | 1425 | if (locked_vma) |
1414 | up_read(&vma->vm_mm->mmap_sem); | 1426 | up_read(&vma->vm_mm->mmap_sem); |
1415 | return ret; | 1427 | return ret; |