aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mremap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/mremap.c')
-rw-r--r--mm/mremap.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/mm/mremap.c b/mm/mremap.c
index f9766f460299..463a25705ac6 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -135,7 +135,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
135 pte_unmap(new_pte - 1); 135 pte_unmap(new_pte - 1);
136 pte_unmap_unlock(old_pte - 1, old_ptl); 136 pte_unmap_unlock(old_pte - 1, old_ptl);
137 if (anon_vma) 137 if (anon_vma)
138 anon_vma_unlock(anon_vma); 138 anon_vma_unlock_write(anon_vma);
139 if (mapping) 139 if (mapping)
140 mutex_unlock(&mapping->i_mmap_mutex); 140 mutex_unlock(&mapping->i_mmap_mutex);
141} 141}
@@ -209,7 +209,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
209 209
210static unsigned long move_vma(struct vm_area_struct *vma, 210static unsigned long move_vma(struct vm_area_struct *vma,
211 unsigned long old_addr, unsigned long old_len, 211 unsigned long old_addr, unsigned long old_len,
212 unsigned long new_len, unsigned long new_addr) 212 unsigned long new_len, unsigned long new_addr, bool *locked)
213{ 213{
214 struct mm_struct *mm = vma->vm_mm; 214 struct mm_struct *mm = vma->vm_mm;
215 struct vm_area_struct *new_vma; 215 struct vm_area_struct *new_vma;
@@ -300,9 +300,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
300 300
301 if (vm_flags & VM_LOCKED) { 301 if (vm_flags & VM_LOCKED) {
302 mm->locked_vm += new_len >> PAGE_SHIFT; 302 mm->locked_vm += new_len >> PAGE_SHIFT;
303 if (new_len > old_len) 303 *locked = true;
304 mlock_vma_pages_range(new_vma, new_addr + old_len,
305 new_addr + new_len);
306 } 304 }
307 305
308 return new_addr; 306 return new_addr;
@@ -367,9 +365,8 @@ Eagain:
367 return ERR_PTR(-EAGAIN); 365 return ERR_PTR(-EAGAIN);
368} 366}
369 367
370static unsigned long mremap_to(unsigned long addr, 368static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
371 unsigned long old_len, unsigned long new_addr, 369 unsigned long new_addr, unsigned long new_len, bool *locked)
372 unsigned long new_len)
373{ 370{
374 struct mm_struct *mm = current->mm; 371 struct mm_struct *mm = current->mm;
375 struct vm_area_struct *vma; 372 struct vm_area_struct *vma;
@@ -419,7 +416,7 @@ static unsigned long mremap_to(unsigned long addr,
419 if (ret & ~PAGE_MASK) 416 if (ret & ~PAGE_MASK)
420 goto out1; 417 goto out1;
421 418
422 ret = move_vma(vma, addr, old_len, new_len, new_addr); 419 ret = move_vma(vma, addr, old_len, new_len, new_addr, locked);
423 if (!(ret & ~PAGE_MASK)) 420 if (!(ret & ~PAGE_MASK))
424 goto out; 421 goto out;
425out1: 422out1:
@@ -457,6 +454,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
457 struct vm_area_struct *vma; 454 struct vm_area_struct *vma;
458 unsigned long ret = -EINVAL; 455 unsigned long ret = -EINVAL;
459 unsigned long charged = 0; 456 unsigned long charged = 0;
457 bool locked = false;
460 458
461 down_write(&current->mm->mmap_sem); 459 down_write(&current->mm->mmap_sem);
462 460
@@ -479,7 +477,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
479 477
480 if (flags & MREMAP_FIXED) { 478 if (flags & MREMAP_FIXED) {
481 if (flags & MREMAP_MAYMOVE) 479 if (flags & MREMAP_MAYMOVE)
482 ret = mremap_to(addr, old_len, new_addr, new_len); 480 ret = mremap_to(addr, old_len, new_addr, new_len,
481 &locked);
483 goto out; 482 goto out;
484 } 483 }
485 484
@@ -521,8 +520,8 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
521 vm_stat_account(mm, vma->vm_flags, vma->vm_file, pages); 520 vm_stat_account(mm, vma->vm_flags, vma->vm_file, pages);
522 if (vma->vm_flags & VM_LOCKED) { 521 if (vma->vm_flags & VM_LOCKED) {
523 mm->locked_vm += pages; 522 mm->locked_vm += pages;
524 mlock_vma_pages_range(vma, addr + old_len, 523 locked = true;
525 addr + new_len); 524 new_addr = addr;
526 } 525 }
527 ret = addr; 526 ret = addr;
528 goto out; 527 goto out;
@@ -548,11 +547,13 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
548 goto out; 547 goto out;
549 } 548 }
550 549
551 ret = move_vma(vma, addr, old_len, new_len, new_addr); 550 ret = move_vma(vma, addr, old_len, new_len, new_addr, &locked);
552 } 551 }
553out: 552out:
554 if (ret & ~PAGE_MASK) 553 if (ret & ~PAGE_MASK)
555 vm_unacct_memory(charged); 554 vm_unacct_memory(charged);
556 up_write(&current->mm->mmap_sem); 555 up_write(&current->mm->mmap_sem);
556 if (locked && new_len > old_len)
557 mm_populate(new_addr + old_len, new_len - old_len);
557 return ret; 558 return ret;
558} 559}