diff options
Diffstat (limited to 'mm/mlock.c')
| -rw-r--r-- | mm/mlock.c | 45 | 
1 files changed, 45 insertions, 0 deletions
diff --git a/mm/mlock.c b/mm/mlock.c index 1ada366570cb..3035a56e7616 100644 --- a/mm/mlock.c +++ b/mm/mlock.c  | |||
| @@ -667,3 +667,48 @@ void user_shm_unlock(size_t size, struct user_struct *user) | |||
| 667 | spin_unlock(&shmlock_user_lock); | 667 | spin_unlock(&shmlock_user_lock); | 
| 668 | free_uid(user); | 668 | free_uid(user); | 
| 669 | } | 669 | } | 
| 670 | |||
| 671 | void *alloc_locked_buffer(size_t size) | ||
| 672 | { | ||
| 673 | unsigned long rlim, vm, pgsz; | ||
| 674 | void *buffer = NULL; | ||
| 675 | |||
| 676 | pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
| 677 | |||
| 678 | down_write(¤t->mm->mmap_sem); | ||
| 679 | |||
| 680 | rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; | ||
| 681 | vm = current->mm->total_vm + pgsz; | ||
| 682 | if (rlim < vm) | ||
| 683 | goto out; | ||
| 684 | |||
| 685 | rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; | ||
| 686 | vm = current->mm->locked_vm + pgsz; | ||
| 687 | if (rlim < vm) | ||
| 688 | goto out; | ||
| 689 | |||
| 690 | buffer = kzalloc(size, GFP_KERNEL); | ||
| 691 | if (!buffer) | ||
| 692 | goto out; | ||
| 693 | |||
| 694 | current->mm->total_vm += pgsz; | ||
| 695 | current->mm->locked_vm += pgsz; | ||
| 696 | |||
| 697 | out: | ||
| 698 | up_write(¤t->mm->mmap_sem); | ||
| 699 | return buffer; | ||
| 700 | } | ||
| 701 | |||
| 702 | void free_locked_buffer(void *buffer, size_t size) | ||
| 703 | { | ||
| 704 | unsigned long pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
| 705 | |||
| 706 | down_write(¤t->mm->mmap_sem); | ||
| 707 | |||
| 708 | current->mm->total_vm -= pgsz; | ||
| 709 | current->mm->locked_vm -= pgsz; | ||
| 710 | |||
| 711 | up_write(¤t->mm->mmap_sem); | ||
| 712 | |||
| 713 | kfree(buffer); | ||
| 714 | } | ||
