From a46ef99d80817a167477ed1c8b4d90ee0c2e726f Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Fri, 20 Apr 2012 16:20:01 -0700
Subject: [PATCH] VM: add "vm_munmap()" helper function

Like the vm_brk() function, this is the same as "do_munmap()", except it
does the VM locking for the caller.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
 arch/ia64/kernel/perfmon.c       | 11 +++--------
 arch/sparc/kernel/sys_sparc_64.c |  7 +------
 arch/x86/kvm/x86.c               |  4 +---
 drivers/gpu/drm/i810/i810_dma.c  |  4 +---
 fs/aio.c                         |  7 ++-----
 include/linux/mm.h               |  1 +
 mm/mmap.c                        | 21 ++++++++++++---------
 mm/nommu.c                       |  9 +++++++--
 8 files changed, 28 insertions(+), 36 deletions(-)

diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 9d0fd7d5bb82..2777310b698b 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -605,9 +605,9 @@ pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f)
 }
 
 static inline unsigned int
-pfm_do_munmap(struct mm_struct *mm, unsigned long addr, size_t len, int acct)
+pfm_vm_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
 {
-	return do_munmap(mm, addr, len);
+	return vm_munmap(mm, addr, len);
 }
 
 static inline unsigned long 
@@ -1473,13 +1473,8 @@ pfm_remove_smpl_mapping(struct task_struct *task, void *vaddr, unsigned long siz
 	/*
 	 * does the actual unmapping
 	 */
-	down_write(&task->mm->mmap_sem);
+	r = pfm_vm_munmap(task->mm, (unsigned long)vaddr, size);
 
-	DPRINT(("down_write done smpl_vaddr=%p size=%lu\n", vaddr, size));
-
-	r = pfm_do_munmap(task->mm, (unsigned long)vaddr, size, 0);
-
-	up_write(&task->mm->mmap_sem);
 	if (r !=0) {
 		printk(KERN_ERR "perfmon: [%d] unable to unmap sampling buffer @%p size=%lu\n", task_pid_nr(task), vaddr, size);
 	}
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 232df9949530..022e57aadf5d 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -566,15 +566,10 @@ out:
 
 SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len)
 {
-	long ret;
-
 	if (invalid_64bit_range(addr, len))
 		return -EINVAL;
 
-	down_write(&current->mm->mmap_sem);
-	ret = do_munmap(current->mm, addr, len);
-	up_write(&current->mm->mmap_sem);
-	return ret;
+	return vm_munmap(current->mm, addr, len);
 }
 
 extern unsigned long do_mremap(unsigned long addr,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4044ce0bf7c1..8beb9ce79364 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6366,10 +6366,8 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 	if (!user_alloc && !old.user_alloc && old.rmap && !npages) {
 		int ret;
 
-		down_write(&current->mm->mmap_sem);
-		ret = do_munmap(current->mm, old.userspace_addr,
+		ret = vm_munmap(current->mm, old.userspace_addr,
 				old.npages * PAGE_SIZE);
-		up_write(&current->mm->mmap_sem);
 		if (ret < 0)
 			printk(KERN_WARNING
 			       "kvm_vm_ioctl_set_memory_region: "
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index 2c8a60c3b98e..b85337f06fbf 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -157,11 +157,9 @@ static int i810_unmap_buffer(struct drm_buf *buf)
 	if (buf_priv->currently_mapped != I810_BUF_MAPPED)
 		return -EINVAL;
 
-	down_write(&current->mm->mmap_sem);
-	retcode = do_munmap(current->mm,
+	retcode = vm_munmap(current->mm,
 			    (unsigned long)buf_priv->virtual,
 			    (size_t) buf->total);
-	up_write(&current->mm->mmap_sem);
 
 	buf_priv->currently_mapped = I810_BUF_UNMAPPED;
 	buf_priv->virtual = NULL;
diff --git a/fs/aio.c b/fs/aio.c
index da887604dfc5..99bd790e8cd2 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -92,11 +92,8 @@ static void aio_free_ring(struct kioctx *ctx)
 	for (i=0; i<info->nr_pages; i++)
 		put_page(info->ring_pages[i]);
 
-	if (info->mmap_size) {
-		down_write(&ctx->mm->mmap_sem);
-		do_munmap(ctx->mm, info->mmap_base, info->mmap_size);
-		up_write(&ctx->mm->mmap_sem);
-	}
+	if (info->mmap_size)
+		vm_munmap(ctx->mm, info->mmap_base, info->mmap_size);
 
 	if (info->ring_pages && info->ring_pages != info->internal_pages)
 		kfree(info->ring_pages);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bfee4ad6680b..cb61950a3aa1 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1417,6 +1417,7 @@ extern int do_munmap(struct mm_struct *, unsigned long, size_t);
 
 /* These take the mm semaphore themselves */
 extern unsigned long vm_brk(unsigned long, unsigned long);
+extern int vm_munmap(struct mm_struct *, unsigned long, size_t);
 
 /* truncate.c */
 extern void truncate_inode_pages(struct address_space *, loff_t);
diff --git a/mm/mmap.c b/mm/mmap.c
index df51891c8646..4af45f519f19 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2107,20 +2107,23 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
 
 	return 0;
 }
-
 EXPORT_SYMBOL(do_munmap);
 
+int vm_munmap(struct mm_struct *mm, unsigned long start, size_t len)
+{
+	int ret;
+
+	down_write(&mm->mmap_sem);
+	ret = do_munmap(mm, start, len);
+	up_write(&mm->mmap_sem);
+	return ret;
+}
+EXPORT_SYMBOL(vm_munmap);
+
 SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
 {
-	int ret;
-	struct mm_struct *mm = current->mm;
-
 	profile_munmap(addr);
-
-	down_write(&mm->mmap_sem);
-	ret = do_munmap(mm, addr, len);
-	up_write(&mm->mmap_sem);
-	return ret;
+	return vm_munmap(current->mm, addr, len);
 }
 
 static inline void verify_mm_writelocked(struct mm_struct *mm)
diff --git a/mm/nommu.c b/mm/nommu.c
index 634193324a6b..11a69b22bd4b 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1709,16 +1709,21 @@ erase_whole_vma:
 }
 EXPORT_SYMBOL(do_munmap);
 
-SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+int vm_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
 {
 	int ret;
-	struct mm_struct *mm = current->mm;
 
 	down_write(&mm->mmap_sem);
 	ret = do_munmap(mm, addr, len);
 	up_write(&mm->mmap_sem);
 	return ret;
 }
+EXPORT_SYMBOL(vm_munmap);
+
+SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+{
+	return vm_munmap(current->mm, addr, len);
+}
 
 /*
  * release all the mappings made in a process's VM space