ARM: shmobile: INTC External IRQ pin driver on sh73a0
[cascardo/linux.git] / mm / mremap.c
index f9766f4..463a257 100644 (file)
@@ -135,7 +135,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
        pte_unmap(new_pte - 1);
        pte_unmap_unlock(old_pte - 1, old_ptl);
        if (anon_vma)
-               anon_vma_unlock(anon_vma);
+               anon_vma_unlock_write(anon_vma);
        if (mapping)
                mutex_unlock(&mapping->i_mmap_mutex);
 }
@@ -209,7 +209,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;
@@ -300,9 +300,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;
@@ -367,9 +365,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;
@@ -419,7 +416,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:
@@ -457,6 +454,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);
 
@@ -479,7 +477,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;
        }
 
@@ -521,8 +520,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;
@@ -548,11 +547,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;
 }