aboutsummaryrefslogtreecommitdiff
path: root/mm/mlock.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@csr.com>2009-01-02 13:17:13 +0000
committerDavid Vrabel <david.vrabel@csr.com>2009-01-02 13:17:13 +0000
commitb21a207141d83a06abc5f492b80204602e02ca44 (patch)
treef0152cde543008c72d7eb5c12c18095ad92785e6 /mm/mlock.c
parent3af373021fa32f8f787bfbdcc1a9277a287bde4e (diff)
parentb58602a4bac012b5f4fc12fe6b46ab237b610d5d (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-upstream
Conflicts: drivers/uwb/wlp/eda.c
Diffstat (limited to 'mm/mlock.c')
-rw-r--r--mm/mlock.c45
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)
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(&current->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(&current->mm->mmap_sem);
+ return buffer;
+}
+
+void free_locked_buffer(void *buffer, size_t size)
+{
+ unsigned long pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+ down_write(&current->mm->mmap_sem);
+
+ current->mm->total_vm -= pgsz;
+ current->mm->locked_vm -= pgsz;
+
+ up_write(&current->mm->mmap_sem);
+
+ kfree(buffer);
+}