]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mm/mmap: Fix vma_shorten() to correctly set vm_pgoff and vm_flags
authorLiam R. Howlett <Liam.Howlett@Oracle.com>
Fri, 20 Nov 2020 19:27:16 +0000 (14:27 -0500)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Sat, 21 Nov 2020 00:57:22 +0000 (19:57 -0500)
Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
mm/mmap.c

index 19b809d238ee78c4ce261b67d82effb83a7b3d55..2ff7ab8a6f61953616cc03323a8d7c3731ef24d2 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2662,7 +2662,6 @@ void vma_shorten(struct vm_area_struct *vma, unsigned long start,
        struct mm_struct *mm = vma->vm_mm;
        unsigned long old_start = vma->vm_start;
        unsigned long old_end = vma->vm_end;
-//     unsigned long old_pgoff = vma->vm_pgoff;
        struct vm_area_struct *next = vma->vm_next;
        struct address_space *mapping = NULL;
        struct rb_root_cached *root = NULL;
@@ -2671,19 +2670,24 @@ void vma_shorten(struct vm_area_struct *vma, unsigned long start,
 
 
        vma_init(unmap, mm);
-       if (end != old_end) { // shortening the start, unmap the end of vma.
-               unmap->vm_start = end;
-               unmap->vm_end = old_end;
-               unmap->vm_next = vma->vm_next;
-               unmap->vm_prev = vma;
-       } else {
+       unmap->vm_pgoff = vma->vm_pgoff;
+       unmap->vm_flags = vma->vm_flags;
+       if (end == old_end) {
+               /* Changing the start of the VMA. */
                unmap->vm_start = old_start;
                unmap->vm_end = start;
                unmap->vm_next = vma;
                unmap->vm_prev = vma->vm_prev;
+       } else {
+               /* unmap will contain the end section of the VMA to be removed  */
+               unmap->vm_start = end;
+               unmap->vm_end = old_end;
+               unmap->vm_next = vma->vm_next;
+               unmap->vm_prev = vma;
+               unmap->vm_pgoff += ((old_start - end) >> PAGE_SHIFT);
        }
 
-       vma_adjust_trans_huge(vma, vma->vm_start, end, 0);
+       vma_adjust_trans_huge(vma, start, end, 0);
 
        if (file) {
                mapping = file->f_mapping;
@@ -2704,11 +2708,12 @@ void vma_shorten(struct vm_area_struct *vma, unsigned long start,
                vma_interval_tree_remove(vma, root);
        }
 
-       if (end == old_end)
+       if (end == old_end) { // Altering the vm_start.
                vma->vm_pgoff += (old_start - start) >> PAGE_SHIFT;
-
-       vma->vm_end = end;
-       vma->vm_start = start;
+               vma->vm_start = start;
+       } else {
+               vma->vm_end = end;
+       }
 
        if (file) {
                vma_interval_tree_insert(vma, root);
@@ -2769,7 +2774,8 @@ int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len,
 
        if (start > vma->vm_start) {
                if (unlikely(vma->vm_end > end)) {
-                       // adjust the same vma twice requires a split.
+                       /* Essentially, this means there is a hole punched in
+                        * this VMA, so a split is unavoidable. */
                        int error;
                        /*
                         * Make sure that map_count on return from munmap() will