diff options
author | Michel Lespinasse <walken@google.com> | 2013-02-22 19:32:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 20:50:11 -0500 |
commit | 81909b842107ef8ca499f46ecb9b7afd87c20c52 (patch) | |
tree | 0af43272c9b0eb7b23fda4ba6cb28e24ae730a93 /mm/mremap.c | |
parent | 128557ffe147c282d8a25e6faeaec6099540bea4 (diff) |
mm: use mm_populate() for mremap() of VM_LOCKED vmas
Signed-off-by: Michel Lespinasse <walken@google.com>
Acked-by: Rik van Riel <riel@redhat.com>
Tested-by: Andy Lutomirski <luto@amacapital.net>
Cc: Greg Ungerer <gregungerer@westnet.com.au>
Cc: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/mremap.c')
-rw-r--r-- | mm/mremap.c | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/mm/mremap.c b/mm/mremap.c index f9766f460299..ebe27a8efa62 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
@@ -209,7 +209,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma, | |||
209 | 209 | ||
210 | static unsigned long move_vma(struct vm_area_struct *vma, | 210 | static 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 | ||
370 | static unsigned long mremap_to(unsigned long addr, | 368 | static 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; |
425 | out1: | 422 | out1: |
@@ -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(¤t->mm->mmap_sem); | 459 | down_write(¤t->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 | } |
553 | out: | 552 | out: |
554 | if (ret & ~PAGE_MASK) | 553 | if (ret & ~PAGE_MASK) |
555 | vm_unacct_memory(charged); | 554 | vm_unacct_memory(charged); |
556 | up_write(¤t->mm->mmap_sem); | 555 | up_write(¤t->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 | } |