mm: rmap use pte lock not mmap_sem to set PageMlocked
[deliverable/linux.git] / mm / rmap.c
index 78a692827a637ce27f7fc2eb5f498b8c18a22b4e..b93fb540c5255a2cc244b2a9f7158603715e00f6 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1304,6 +1304,10 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
        int ret = SWAP_AGAIN;
        enum ttu_flags flags = (enum ttu_flags)arg;
 
+       /* munlock has nothing to gain from examining un-locked vmas */
+       if ((flags & TTU_MUNLOCK) && !(vma->vm_flags & VM_LOCKED))
+               goto out;
+
        pte = page_check_address(page, mm, address, &ptl, 0);
        if (!pte)
                goto out;
@@ -1314,9 +1318,12 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
         * skipped over this mm) then we should reactivate it.
         */
        if (!(flags & TTU_IGNORE_MLOCK)) {
-               if (vma->vm_flags & VM_LOCKED)
-                       goto out_mlock;
-
+               if (vma->vm_flags & VM_LOCKED) {
+                       /* Holding pte lock, we do *not* need mmap_sem here */
+                       mlock_vma_page(page);
+                       ret = SWAP_MLOCK;
+                       goto out_unmap;
+               }
                if (flags & TTU_MUNLOCK)
                        goto out_unmap;
        }
@@ -1421,31 +1428,10 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
 
 out_unmap:
        pte_unmap_unlock(pte, ptl);
-       if (ret != SWAP_FAIL && !(flags & TTU_MUNLOCK))
+       if (ret != SWAP_FAIL && ret != SWAP_MLOCK && !(flags & TTU_MUNLOCK))
                mmu_notifier_invalidate_page(mm, address);
 out:
        return ret;
-
-out_mlock:
-       pte_unmap_unlock(pte, ptl);
-
-
-       /*
-        * We need mmap_sem locking, Otherwise VM_LOCKED check makes
-        * unstable result and race. Plus, We can't wait here because
-        * we now hold anon_vma->rwsem or mapping->i_mmap_rwsem.
-        * if trylock failed, the page remain in evictable lru and later
-        * vmscan could retry to move the page to unevictable lru if the
-        * page is actually mlocked.
-        */
-       if (down_read_trylock(&vma->vm_mm->mmap_sem)) {
-               if (vma->vm_flags & VM_LOCKED) {
-                       mlock_vma_page(page);
-                       ret = SWAP_MLOCK;
-               }
-               up_read(&vma->vm_mm->mmap_sem);
-       }
-       return ret;
 }
 
 bool is_vma_temporary_stack(struct vm_area_struct *vma)
This page took 0.040107 seconds and 5 git commands to generate.