Signed-off-by: Michel Lespinasse <wal...@google.com>

---
 mm/mremap.c |   25 +++++++++++++------------
 1 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/mm/mremap.c b/mm/mremap.c
index 1b61c2d3307a..c5a8bf344b1f 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -208,7 +208,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
 
 static unsigned long move_vma(struct vm_area_struct *vma,
                unsigned long old_addr, unsigned long old_len,
-               unsigned long new_len, unsigned long new_addr)
+               unsigned long new_len, unsigned long new_addr, bool *locked)
 {
        struct mm_struct *mm = vma->vm_mm;
        struct vm_area_struct *new_vma;
@@ -299,9 +299,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
 
        if (vm_flags & VM_LOCKED) {
                mm->locked_vm += new_len >> PAGE_SHIFT;
-               if (new_len > old_len)
-                       mlock_vma_pages_range(new_vma, new_addr + old_len,
-                                                      new_addr + new_len);
+               *locked = true;
        }
 
        return new_addr;
@@ -366,9 +364,8 @@ Eagain:
        return ERR_PTR(-EAGAIN);
 }
 
-static unsigned long mremap_to(unsigned long addr,
-       unsigned long old_len, unsigned long new_addr,
-       unsigned long new_len)
+static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
+               unsigned long new_addr, unsigned long new_len, bool *locked)
 {
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
@@ -418,7 +415,7 @@ static unsigned long mremap_to(unsigned long addr,
        if (ret & ~PAGE_MASK)
                goto out1;
 
-       ret = move_vma(vma, addr, old_len, new_len, new_addr);
+       ret = move_vma(vma, addr, old_len, new_len, new_addr, locked);
        if (!(ret & ~PAGE_MASK))
                goto out;
 out1:
@@ -456,6 +453,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, 
old_len,
        struct vm_area_struct *vma;
        unsigned long ret = -EINVAL;
        unsigned long charged = 0;
+       bool locked = false;
 
        down_write(&current->mm->mmap_sem);
 
@@ -478,7 +476,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, 
old_len,
 
        if (flags & MREMAP_FIXED) {
                if (flags & MREMAP_MAYMOVE)
-                       ret = mremap_to(addr, old_len, new_addr, new_len);
+                       ret = mremap_to(addr, old_len, new_addr, new_len,
+                                       &locked);
                goto out;
        }
 
@@ -520,8 +519,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, 
old_len,
                        vm_stat_account(mm, vma->vm_flags, vma->vm_file, pages);
                        if (vma->vm_flags & VM_LOCKED) {
                                mm->locked_vm += pages;
-                               mlock_vma_pages_range(vma, addr + old_len,
-                                                  addr + new_len);
+                               locked = true;
+                               new_addr = addr;
                        }
                        ret = addr;
                        goto out;
@@ -547,11 +546,13 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned 
long, old_len,
                        goto out;
                }
 
-               ret = move_vma(vma, addr, old_len, new_len, new_addr);
+               ret = move_vma(vma, addr, old_len, new_len, new_addr, &locked);
        }
 out:
        if (ret & ~PAGE_MASK)
                vm_unacct_memory(charged);
        up_write(&current->mm->mmap_sem);
+       if (locked && new_len > old_len)
+               mm_populate(new_addr + old_len, new_len - old_len);
        return ret;
 }
-- 
1.7.7.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to