Browse Source

mm: new arch_remap() hook

Some architectures would like to be triggered when a memory area is moved
through the mremap system call.

This patch introduces a new arch_remap() mm hook which is placed in the
path of mremap, and is called before the old area is unmapped (and the
arch_unmap() hook is called).

Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Laurent Dufour 10 years ago
parent
commit
4abad2ca4a
2 changed files with 20 additions and 6 deletions
  1. 9 0
      include/linux/mm-arch-hooks.h
  2. 11 6
      mm/mremap.c

+ 9 - 0
include/linux/mm-arch-hooks.h

@@ -13,4 +13,13 @@
 
 
 #include <asm/mm-arch-hooks.h>
 #include <asm/mm-arch-hooks.h>
 
 
+#ifndef arch_remap
+static inline void arch_remap(struct mm_struct *mm,
+			      unsigned long old_start, unsigned long old_end,
+			      unsigned long new_start, unsigned long new_end)
+{
+}
+#define arch_remap arch_remap
+#endif
+
 #endif /* _LINUX_MM_ARCH_HOOKS_H */
 #endif /* _LINUX_MM_ARCH_HOOKS_H */

+ 11 - 6
mm/mremap.c

@@ -22,6 +22,7 @@
 #include <linux/mmu_notifier.h>
 #include <linux/mmu_notifier.h>
 #include <linux/sched/sysctl.h>
 #include <linux/sched/sysctl.h>
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>
+#include <linux/mm-arch-hooks.h>
 
 
 #include <asm/cacheflush.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/tlbflush.h>
@@ -286,13 +287,17 @@ static unsigned long move_vma(struct vm_area_struct *vma,
 		old_len = new_len;
 		old_len = new_len;
 		old_addr = new_addr;
 		old_addr = new_addr;
 		new_addr = -ENOMEM;
 		new_addr = -ENOMEM;
-	} else if (vma->vm_file && vma->vm_file->f_op->mremap) {
-		err = vma->vm_file->f_op->mremap(vma->vm_file, new_vma);
-		if (err < 0) {
-			move_page_tables(new_vma, new_addr, vma, old_addr,
-					 moved_len, true);
-			return err;
+	} else {
+		if (vma->vm_file && vma->vm_file->f_op->mremap) {
+			err = vma->vm_file->f_op->mremap(vma->vm_file, new_vma);
+			if (err < 0) {
+				move_page_tables(new_vma, new_addr, vma,
+						 old_addr, moved_len, true);
+				return err;
+			}
 		}
 		}
+		arch_remap(mm, old_addr, old_addr + old_len,
+			   new_addr, new_addr + new_len);
 	}
 	}
 
 
 	/* Conceal VM_ACCOUNT so old reservation is not undone */
 	/* Conceal VM_ACCOUNT so old reservation is not undone */