aboutsummaryrefslogtreecommitdiffstats
path: root/mm/mlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/mlock.c')
-rw-r--r--mm/mlock.c56
1 files changed, 8 insertions, 48 deletions
diff --git a/mm/mlock.c b/mm/mlock.c
index e125156c664e..037161d61b4e 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -294,14 +294,10 @@ static inline int __mlock_posix_error_return(long retval)
294 * 294 *
295 * return number of pages [> 0] to be removed from locked_vm on success 295 * return number of pages [> 0] to be removed from locked_vm on success
296 * of "special" vmas. 296 * of "special" vmas.
297 *
298 * return negative error if vma spanning @start-@range disappears while
299 * mmap semaphore is dropped. Unlikely?
300 */ 297 */
301long mlock_vma_pages_range(struct vm_area_struct *vma, 298long mlock_vma_pages_range(struct vm_area_struct *vma,
302 unsigned long start, unsigned long end) 299 unsigned long start, unsigned long end)
303{ 300{
304 struct mm_struct *mm = vma->vm_mm;
305 int nr_pages = (end - start) / PAGE_SIZE; 301 int nr_pages = (end - start) / PAGE_SIZE;
306 BUG_ON(!(vma->vm_flags & VM_LOCKED)); 302 BUG_ON(!(vma->vm_flags & VM_LOCKED));
307 303
@@ -314,20 +310,11 @@ long mlock_vma_pages_range(struct vm_area_struct *vma,
314 if (!((vma->vm_flags & (VM_DONTEXPAND | VM_RESERVED)) || 310 if (!((vma->vm_flags & (VM_DONTEXPAND | VM_RESERVED)) ||
315 is_vm_hugetlb_page(vma) || 311 is_vm_hugetlb_page(vma) ||
316 vma == get_gate_vma(current))) { 312 vma == get_gate_vma(current))) {
317 long error;
318 downgrade_write(&mm->mmap_sem);
319
320 error = __mlock_vma_pages_range(vma, start, end, 1);
321 313
322 up_read(&mm->mmap_sem); 314 __mlock_vma_pages_range(vma, start, end, 1);
323 /* vma can change or disappear */
324 down_write(&mm->mmap_sem);
325 vma = find_vma(mm, start);
326 /* non-NULL vma must contain @start, but need to check @end */
327 if (!vma || end > vma->vm_end)
328 return -ENOMEM;
329 315
330 return 0; /* hide other errors from mmap(), et al */ 316 /* Hide errors from mmap() and other callers */
317 return 0;
331 } 318 }
332 319
333 /* 320 /*
@@ -438,41 +425,14 @@ success:
438 vma->vm_flags = newflags; 425 vma->vm_flags = newflags;
439 426
440 if (lock) { 427 if (lock) {
441 /*
442 * mmap_sem is currently held for write. Downgrade the write
443 * lock to a read lock so that other faults, mmap scans, ...
444 * while we fault in all pages.
445 */
446 downgrade_write(&mm->mmap_sem);
447
448 ret = __mlock_vma_pages_range(vma, start, end, 1); 428 ret = __mlock_vma_pages_range(vma, start, end, 1);
449 429
450 /* 430 if (ret > 0) {
451 * Need to reacquire mmap sem in write mode, as our callers
452 * expect this. We have no support for atomically upgrading
453 * a sem to write, so we need to check for ranges while sem
454 * is unlocked.
455 */
456 up_read(&mm->mmap_sem);
457 /* vma can change or disappear */
458 down_write(&mm->mmap_sem);
459 *prev = find_vma(mm, start);
460 /* non-NULL *prev must contain @start, but need to check @end */
461 if (!(*prev) || end > (*prev)->vm_end)
462 ret = -ENOMEM;
463 else if (ret > 0) {
464 mm->locked_vm -= ret; 431 mm->locked_vm -= ret;
465 ret = 0; 432 ret = 0;
466 } else 433 } else
467 ret = __mlock_posix_error_return(ret); /* translate if needed */ 434 ret = __mlock_posix_error_return(ret); /* translate if needed */
468 } else { 435 } else {
469 /*
470 * TODO: for unlocking, pages will already be resident, so
471 * we don't need to wait for allocations/reclaim/pagein, ...
472 * However, unlocking a very large region can still take a
473 * while. Should we downgrade the semaphore for both lock
474 * AND unlock ?
475 */
476 __mlock_vma_pages_range(vma, start, end, 0); 436 __mlock_vma_pages_range(vma, start, end, 0);
477 } 437 }
478 438
@@ -530,7 +490,7 @@ static int do_mlock(unsigned long start, size_t len, int on)
530 return error; 490 return error;
531} 491}
532 492
533asmlinkage long sys_mlock(unsigned long start, size_t len) 493SYSCALL_DEFINE2(mlock, unsigned long, start, size_t, len)
534{ 494{
535 unsigned long locked; 495 unsigned long locked;
536 unsigned long lock_limit; 496 unsigned long lock_limit;
@@ -558,7 +518,7 @@ asmlinkage long sys_mlock(unsigned long start, size_t len)
558 return error; 518 return error;
559} 519}
560 520
561asmlinkage long sys_munlock(unsigned long start, size_t len) 521SYSCALL_DEFINE2(munlock, unsigned long, start, size_t, len)
562{ 522{
563 int ret; 523 int ret;
564 524
@@ -595,7 +555,7 @@ out:
595 return 0; 555 return 0;
596} 556}
597 557
598asmlinkage long sys_mlockall(int flags) 558SYSCALL_DEFINE1(mlockall, int, flags)
599{ 559{
600 unsigned long lock_limit; 560 unsigned long lock_limit;
601 int ret = -EINVAL; 561 int ret = -EINVAL;
@@ -623,7 +583,7 @@ out:
623 return ret; 583 return ret;
624} 584}
625 585
626asmlinkage long sys_munlockall(void) 586SYSCALL_DEFINE0(munlockall)
627{ 587{
628 int ret; 588 int ret;
629 589