]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mm: Fix __vma_adjust() writes for the maple tree
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Tue, 2 May 2023 00:27:52 +0000 (20:27 -0400)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Tue, 2 May 2023 03:00:31 +0000 (23:00 -0400)
Only write when necessary to the maple tree.  This should only occur
when the VMA changes.  In the __vma_adjust() case, it is either the vma
when it is expanded, the next vma when the boundary expands into 'vma',
writing the 'insert', or when vma expands/shrinks for shift_arg_pages().

The mas_preallocate() setup should track the intended write to ensure
the correct number of nodes are preallocated for the pending write.

Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
mm/mmap.c

index 5ea97c037ab2dd4be995f151dd5e28e9397b92e8..c374ff80eb693f73657b1c9abdb9ef2918f92142 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -628,7 +628,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
        bool vma_changed = false;
        long adjust_next = 0;
        int remove_next = 0;
-       MA_STATE(mas, &mm->mm_mt, 0, 0);
+       MA_STATE(mas, &mm->mm_mt, start, end - 1);
        struct vm_area_struct *exporter = NULL, *importer = NULL;
 
        if (next && !insert) {
@@ -713,6 +713,13 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
                }
        }
 
+       if (adjust_next < 0)
+               mas_set_range(&mas, next->vm_start + adjust_next,
+                             next->vm_end - 1);
+       else if (insert)
+               mas_set_range(&mas, insert->vm_start, insert->vm_end - 1);
+
+
        if (mas_preallocate(&mas, vma, GFP_KERNEL))
                return -ENOMEM;
 
@@ -757,24 +764,23 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
        }
 
        if (start != vma->vm_start) {
-               if ((vma->vm_start < start) &&
-                   (!insert || (insert->vm_end != start))) {
+               if ((vma->vm_start < start) && !insert) {
                        vma_mas_szero(&mas, vma->vm_start, start);
                        VM_WARN_ON(insert && insert->vm_start > vma->vm_start);
-               } else {
+               } else if (!insert) {
                        vma_changed = true;
                }
                vma->vm_start = start;
        }
        if (end != vma->vm_end) {
                if (vma->vm_end > end) {
-                       if (!insert || (insert->vm_start != end)) {
+                       if (adjust_next >= 0 && !insert) {
                                vma_mas_szero(&mas, end, vma->vm_end);
                                mas_reset(&mas);
                                VM_WARN_ON(insert &&
                                           insert->vm_end < vma->vm_end);
                        }
-               } else {
+               } else if (!insert) {
                        vma_changed = true;
                }
                vma->vm_end = end;