diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-12-29 09:45:15 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-29 09:45:15 +0100 |
commit | e1df957670aef74ffd9a4ad93e6d2c90bf6b4845 (patch) | |
tree | bca1fcfef55b3e3e82c9a822b4ac6428fce2b419 /mm/mlock.c | |
parent | 2b583d8bc8d7105b58d7481a4a0ceb718dac49c6 (diff) | |
parent | 3c92ec8ae91ecf59d88c798301833d7cf83f2179 (diff) |
Merge branch 'linus' into perfcounters/core
Conflicts:
fs/exec.c
include/linux/init_task.h
Simple context conflicts.
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 1ada366570c..3035a56e761 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -667,3 +667,48 @@ void user_shm_unlock(size_t size, struct user_struct *user) spin_unlock(&shmlock_user_lock); free_uid(user); } + +void *alloc_locked_buffer(size_t size) +{ + unsigned long rlim, vm, pgsz; + void *buffer = NULL; + + pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT; + + down_write(¤t->mm->mmap_sem); + + rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; + vm = current->mm->total_vm + pgsz; + if (rlim < vm) + goto out; + + rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; + vm = current->mm->locked_vm + pgsz; + if (rlim < vm) + goto out; + + buffer = kzalloc(size, GFP_KERNEL); + if (!buffer) + goto out; + + current->mm->total_vm += pgsz; + current->mm->locked_vm += pgsz; + + out: + up_write(¤t->mm->mmap_sem); + return buffer; +} + +void free_locked_buffer(void *buffer, size_t size) +{ + unsigned long pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT; + + down_write(¤t->mm->mmap_sem); + + current->mm->total_vm -= pgsz; + current->mm->locked_vm -= pgsz; + + up_write(¤t->mm->mmap_sem); + + kfree(buffer); +} |