uprobes: __replace_page() needs munlock_vma_page()
authorOleg Nesterov <oleg@redhat.com>
Sun, 29 Jul 2012 18:22:49 +0000 (20:22 +0200)
committerIngo Molnar <mingo@kernel.org>
Mon, 30 Jul 2012 09:27:25 +0000 (11:27 +0200)
Like do_wp_page(), __replace_page() should do munlock_vma_page()
for the case when the old page still has other !VM_LOCKED
mappings. Unfortunately this needs mm/internal.h.

Also, move put_page() outside of ptl lock. This doesn't really
matter but looks a bit better.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar.vnet.ibm.com>
Cc: Anton Arapov <anton@redhat.com>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/20120729182249.GA20372@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
kernel/events/uprobes.c

index bb30a4f..c08a22d 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/swap.h>                /* try_to_free_swap */
 #include <linux/ptrace.h>      /* user_enable_single_step */
 #include <linux/kdebug.h>      /* notifier mechanism */
+#include "../../mm/internal.h" /* munlock_vma_page */
 
 #include <linux/uprobes.h>
 
@@ -141,7 +142,7 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
        pte_t *ptep;
        int err;
 
-       /* freeze PageSwapCache() for try_to_free_swap() below */
+       /* For try_to_free_swap() and munlock_vma_page() below */
        lock_page(page);
 
        err = -EAGAIN;
@@ -164,9 +165,12 @@ static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
        page_remove_rmap(page);
        if (!page_mapped(page))
                try_to_free_swap(page);
-       put_page(page);
        pte_unmap_unlock(ptep, ptl);
 
+       if (vma->vm_flags & VM_LOCKED)
+               munlock_vma_page(page);
+       put_page(page);
+
        err = 0;
  unlock:
        unlock_page(page);