aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAndrea Arcangeli <aarcange@redhat.com>2015-09-04 18:46:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-04 19:54:41 -0400
commit19a809afe2fe089317226bbe5c5a1ce7f53dcdca (patch)
tree578abd63bf6a68dce4d7e20be1641e0111890914 /mm
parent6b251fc96cf2cdf1ce4b5db055547e2a5679bc77 (diff)
userfaultfd: teach vma_merge to merge across vma->vm_userfaultfd_ctx
vma->vm_userfaultfd_ctx is yet another vma parameter that vma_merge must be aware about so that we can merge vmas back like they were originally before arming the userfaultfd on some memory range. Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Acked-by: Pavel Emelyanov <xemul@parallels.com> Cc: Sanidhya Kashyap <sanidhya.gatech@gmail.com> Cc: zhang.zhanghailiang@huawei.com Cc: "Kirill A. Shutemov" <kirill@shutemov.name> Cc: Andres Lagar-Cavilla <andreslc@google.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Rik van Riel <riel@redhat.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Hugh Dickins <hughd@google.com> Cc: Peter Feiner <pfeiner@google.com> Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: "Huangpeng (Peter)" <peter.huangpeng@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/madvise.c3
-rw-r--r--mm/mempolicy.c4
-rw-r--r--mm/mlock.c3
-rw-r--r--mm/mmap.c40
-rw-r--r--mm/mprotect.c3
5 files changed, 35 insertions, 18 deletions
diff --git a/mm/madvise.c b/mm/madvise.c
index 64bb8a22110c..911357973905 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -103,7 +103,8 @@ static long madvise_behavior(struct vm_area_struct *vma,
103 103
104 pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); 104 pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
105 *prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma, 105 *prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma,
106 vma->vm_file, pgoff, vma_policy(vma)); 106 vma->vm_file, pgoff, vma_policy(vma),
107 vma->vm_userfaultfd_ctx);
107 if (*prev) { 108 if (*prev) {
108 vma = *prev; 109 vma = *prev;
109 goto success; 110 goto success;
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 99d4c1d0b858..a7f1e0d1d6b8 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -722,8 +722,8 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
722 pgoff = vma->vm_pgoff + 722 pgoff = vma->vm_pgoff +
723 ((vmstart - vma->vm_start) >> PAGE_SHIFT); 723 ((vmstart - vma->vm_start) >> PAGE_SHIFT);
724 prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags, 724 prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags,
725 vma->anon_vma, vma->vm_file, pgoff, 725 vma->anon_vma, vma->vm_file, pgoff,
726 new_pol); 726 new_pol, vma->vm_userfaultfd_ctx);
727 if (prev) { 727 if (prev) {
728 vma = prev; 728 vma = prev;
729 next = vma->vm_next; 729 next = vma->vm_next;
diff --git a/mm/mlock.c b/mm/mlock.c
index 6fd2cf15e868..25936680064f 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -510,7 +510,8 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
510 510
511 pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); 511 pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
512 *prev = vma_merge(mm, *prev, start, end, newflags, vma->anon_vma, 512 *prev = vma_merge(mm, *prev, start, end, newflags, vma->anon_vma,
513 vma->vm_file, pgoff, vma_policy(vma)); 513 vma->vm_file, pgoff, vma_policy(vma),
514 vma->vm_userfaultfd_ctx);
514 if (*prev) { 515 if (*prev) {
515 vma = *prev; 516 vma = *prev;
516 goto success; 517 goto success;
diff --git a/mm/mmap.c b/mm/mmap.c
index f126923ce683..82db4fc0a9d3 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -41,6 +41,7 @@
41#include <linux/notifier.h> 41#include <linux/notifier.h>
42#include <linux/memory.h> 42#include <linux/memory.h>
43#include <linux/printk.h> 43#include <linux/printk.h>
44#include <linux/userfaultfd_k.h>
44 45
45#include <asm/uaccess.h> 46#include <asm/uaccess.h>
46#include <asm/cacheflush.h> 47#include <asm/cacheflush.h>
@@ -919,7 +920,8 @@ again: remove_next = 1 + (end > next->vm_end);
919 * per-vma resources, so we don't attempt to merge those. 920 * per-vma resources, so we don't attempt to merge those.
920 */ 921 */
921static inline int is_mergeable_vma(struct vm_area_struct *vma, 922static inline int is_mergeable_vma(struct vm_area_struct *vma,
922 struct file *file, unsigned long vm_flags) 923 struct file *file, unsigned long vm_flags,
924 struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
923{ 925{
924 /* 926 /*
925 * VM_SOFTDIRTY should not prevent from VMA merging, if we 927 * VM_SOFTDIRTY should not prevent from VMA merging, if we
@@ -935,6 +937,8 @@ static inline int is_mergeable_vma(struct vm_area_struct *vma,
935 return 0; 937 return 0;
936 if (vma->vm_ops && vma->vm_ops->close) 938 if (vma->vm_ops && vma->vm_ops->close)
937 return 0; 939 return 0;
940 if (!is_mergeable_vm_userfaultfd_ctx(vma, vm_userfaultfd_ctx))
941 return 0;
938 return 1; 942 return 1;
939} 943}
940 944
@@ -965,9 +969,11 @@ static inline int is_mergeable_anon_vma(struct anon_vma *anon_vma1,
965 */ 969 */
966static int 970static int
967can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags, 971can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags,
968 struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff) 972 struct anon_vma *anon_vma, struct file *file,
973 pgoff_t vm_pgoff,
974 struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
969{ 975{
970 if (is_mergeable_vma(vma, file, vm_flags) && 976 if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx) &&
971 is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) { 977 is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) {
972 if (vma->vm_pgoff == vm_pgoff) 978 if (vma->vm_pgoff == vm_pgoff)
973 return 1; 979 return 1;
@@ -984,9 +990,11 @@ can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags,
984 */ 990 */
985static int 991static int
986can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, 992can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
987 struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff) 993 struct anon_vma *anon_vma, struct file *file,
994 pgoff_t vm_pgoff,
995 struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
988{ 996{
989 if (is_mergeable_vma(vma, file, vm_flags) && 997 if (is_mergeable_vma(vma, file, vm_flags, vm_userfaultfd_ctx) &&
990 is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) { 998 is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) {
991 pgoff_t vm_pglen; 999 pgoff_t vm_pglen;
992 vm_pglen = vma_pages(vma); 1000 vm_pglen = vma_pages(vma);
@@ -1029,7 +1037,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
1029 struct vm_area_struct *prev, unsigned long addr, 1037 struct vm_area_struct *prev, unsigned long addr,
1030 unsigned long end, unsigned long vm_flags, 1038 unsigned long end, unsigned long vm_flags,
1031 struct anon_vma *anon_vma, struct file *file, 1039 struct anon_vma *anon_vma, struct file *file,
1032 pgoff_t pgoff, struct mempolicy *policy) 1040 pgoff_t pgoff, struct mempolicy *policy,
1041 struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
1033{ 1042{
1034 pgoff_t pglen = (end - addr) >> PAGE_SHIFT; 1043 pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
1035 struct vm_area_struct *area, *next; 1044 struct vm_area_struct *area, *next;
@@ -1056,14 +1065,17 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
1056 if (prev && prev->vm_end == addr && 1065 if (prev && prev->vm_end == addr &&
1057 mpol_equal(vma_policy(prev), policy) && 1066 mpol_equal(vma_policy(prev), policy) &&
1058 can_vma_merge_after(prev, vm_flags, 1067 can_vma_merge_after(prev, vm_flags,
1059 anon_vma, file, pgoff)) { 1068 anon_vma, file, pgoff,
1069 vm_userfaultfd_ctx)) {
1060 /* 1070 /*
1061 * OK, it can. Can we now merge in the successor as well? 1071 * OK, it can. Can we now merge in the successor as well?
1062 */ 1072 */
1063 if (next && end == next->vm_start && 1073 if (next && end == next->vm_start &&
1064 mpol_equal(policy, vma_policy(next)) && 1074 mpol_equal(policy, vma_policy(next)) &&
1065 can_vma_merge_before(next, vm_flags, 1075 can_vma_merge_before(next, vm_flags,
1066 anon_vma, file, pgoff+pglen) && 1076 anon_vma, file,
1077 pgoff+pglen,
1078 vm_userfaultfd_ctx) &&
1067 is_mergeable_anon_vma(prev->anon_vma, 1079 is_mergeable_anon_vma(prev->anon_vma,
1068 next->anon_vma, NULL)) { 1080 next->anon_vma, NULL)) {
1069 /* cases 1, 6 */ 1081 /* cases 1, 6 */
@@ -1084,7 +1096,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
1084 if (next && end == next->vm_start && 1096 if (next && end == next->vm_start &&
1085 mpol_equal(policy, vma_policy(next)) && 1097 mpol_equal(policy, vma_policy(next)) &&
1086 can_vma_merge_before(next, vm_flags, 1098 can_vma_merge_before(next, vm_flags,
1087 anon_vma, file, pgoff+pglen)) { 1099 anon_vma, file, pgoff+pglen,
1100 vm_userfaultfd_ctx)) {
1088 if (prev && addr < prev->vm_end) /* case 4 */ 1101 if (prev && addr < prev->vm_end) /* case 4 */
1089 err = vma_adjust(prev, prev->vm_start, 1102 err = vma_adjust(prev, prev->vm_start,
1090 addr, prev->vm_pgoff, NULL); 1103 addr, prev->vm_pgoff, NULL);
@@ -1570,8 +1583,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
1570 /* 1583 /*
1571 * Can we just expand an old mapping? 1584 * Can we just expand an old mapping?
1572 */ 1585 */
1573 vma = vma_merge(mm, prev, addr, addr + len, vm_flags, NULL, file, pgoff, 1586 vma = vma_merge(mm, prev, addr, addr + len, vm_flags,
1574 NULL); 1587 NULL, file, pgoff, NULL, NULL_VM_UFFD_CTX);
1575 if (vma) 1588 if (vma)
1576 goto out; 1589 goto out;
1577 1590
@@ -2757,7 +2770,7 @@ static unsigned long do_brk(unsigned long addr, unsigned long len)
2757 2770
2758 /* Can we just expand an old private anonymous mapping? */ 2771 /* Can we just expand an old private anonymous mapping? */
2759 vma = vma_merge(mm, prev, addr, addr + len, flags, 2772 vma = vma_merge(mm, prev, addr, addr + len, flags,
2760 NULL, NULL, pgoff, NULL); 2773 NULL, NULL, pgoff, NULL, NULL_VM_UFFD_CTX);
2761 if (vma) 2774 if (vma)
2762 goto out; 2775 goto out;
2763 2776
@@ -2913,7 +2926,8 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
2913 if (find_vma_links(mm, addr, addr + len, &prev, &rb_link, &rb_parent)) 2926 if (find_vma_links(mm, addr, addr + len, &prev, &rb_link, &rb_parent))
2914 return NULL; /* should never get here */ 2927 return NULL; /* should never get here */
2915 new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags, 2928 new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags,
2916 vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma)); 2929 vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
2930 vma->vm_userfaultfd_ctx);
2917 if (new_vma) { 2931 if (new_vma) {
2918 /* 2932 /*
2919 * Source vma may have been merged into new_vma 2933 * Source vma may have been merged into new_vma
diff --git a/mm/mprotect.c b/mm/mprotect.c
index e7d6f1171ecb..ef5be8eaab00 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -292,7 +292,8 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
292 */ 292 */
293 pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); 293 pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
294 *pprev = vma_merge(mm, *pprev, start, end, newflags, 294 *pprev = vma_merge(mm, *pprev, start, end, newflags,
295 vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma)); 295 vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
296 vma->vm_userfaultfd_ctx);
296 if (*pprev) { 297 if (*pprev) {
297 vma = *pprev; 298 vma = *pprev;
298 goto success; 299 goto success;