]> Pileus Git - ~andy/linux/blobdiff - mm/ksm.c
ip6tnl/sit: drop packet if ECN present with not-ECT
[~andy/linux] / mm / ksm.c
index 9638620a7530ed2b35ab381e751ab0ab90018cdb..ae539f0b8aa1115ce2ba86ae8b94ec48a79b8333 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -709,15 +709,22 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
        spinlock_t *ptl;
        int swapped;
        int err = -EFAULT;
+       unsigned long mmun_start;       /* For mmu_notifiers */
+       unsigned long mmun_end;         /* For mmu_notifiers */
 
        addr = page_address_in_vma(page, vma);
        if (addr == -EFAULT)
                goto out;
 
        BUG_ON(PageTransCompound(page));
+
+       mmun_start = addr;
+       mmun_end   = addr + PAGE_SIZE;
+       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+
        ptep = page_check_address(page, mm, addr, &ptl, 0);
        if (!ptep)
-               goto out;
+               goto out_mn;
 
        if (pte_write(*ptep) || pte_dirty(*ptep)) {
                pte_t entry;
@@ -752,6 +759,8 @@ static int write_protect_page(struct vm_area_struct *vma, struct page *page,
 
 out_unlock:
        pte_unmap_unlock(ptep, ptl);
+out_mn:
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 out:
        return err;
 }
@@ -776,6 +785,8 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
        spinlock_t *ptl;
        unsigned long addr;
        int err = -EFAULT;
+       unsigned long mmun_start;       /* For mmu_notifiers */
+       unsigned long mmun_end;         /* For mmu_notifiers */
 
        addr = page_address_in_vma(page, vma);
        if (addr == -EFAULT)
@@ -794,10 +805,14 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
        if (!pmd_present(*pmd))
                goto out;
 
+       mmun_start = addr;
+       mmun_end   = addr + PAGE_SIZE;
+       mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
+
        ptep = pte_offset_map_lock(mm, pmd, addr, &ptl);
        if (!pte_same(*ptep, orig_pte)) {
                pte_unmap_unlock(ptep, ptl);
-               goto out;
+               goto out_mn;
        }
 
        get_page(kpage);
@@ -814,6 +829,8 @@ static int replace_page(struct vm_area_struct *vma, struct page *page,
 
        pte_unmap_unlock(ptep, ptl);
        err = 0;
+out_mn:
+       mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
 out:
        return err;
 }
@@ -1586,7 +1603,7 @@ struct page *ksm_does_need_to_copy(struct page *page,
                SetPageSwapBacked(new_page);
                __set_page_locked(new_page);
 
-               if (page_evictable(new_page, vma))
+               if (!mlocked_vma_newpage(vma, new_page))
                        lru_cache_add_lru(new_page, LRU_ACTIVE_ANON);
                else
                        add_page_to_unevictable_list(new_page);
@@ -1618,7 +1635,8 @@ again:
                struct vm_area_struct *vma;
 
                anon_vma_lock(anon_vma);
-               list_for_each_entry(vmac, &anon_vma->head, same_anon_vma) {
+               anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root,
+                                              0, ULONG_MAX) {
                        vma = vmac->vma;
                        if (rmap_item->address < vma->vm_start ||
                            rmap_item->address >= vma->vm_end)
@@ -1671,7 +1689,8 @@ again:
                struct vm_area_struct *vma;
 
                anon_vma_lock(anon_vma);
-               list_for_each_entry(vmac, &anon_vma->head, same_anon_vma) {
+               anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root,
+                                              0, ULONG_MAX) {
                        vma = vmac->vma;
                        if (rmap_item->address < vma->vm_start ||
                            rmap_item->address >= vma->vm_end)
@@ -1723,7 +1742,8 @@ again:
                struct vm_area_struct *vma;
 
                anon_vma_lock(anon_vma);
-               list_for_each_entry(vmac, &anon_vma->head, same_anon_vma) {
+               anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root,
+                                              0, ULONG_MAX) {
                        vma = vmac->vma;
                        if (rmap_item->address < vma->vm_start ||
                            rmap_item->address >= vma->vm_end)