]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fs/exec: Remove vma_adjust() call and use mmap and maple tree calls.
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Tue, 10 May 2022 02:41:23 +0000 (22:41 -0400)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Wed, 11 May 2022 14:46:53 +0000 (10:46 -0400)
Remove yet another user of vma_adjust().

Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
fs/exec.c
include/linux/mm.h
mm/mmap.c

index b5e3bfd52b533da2b4c276ed8300dc16ae6844b6..be67f089a5f67e831a2389f2f8cead1df9b2c0e0 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -28,6 +28,7 @@
 #include <linux/file.h>
 #include <linux/fdtable.h>
 #include <linux/mm.h>
+#include <linux/maple_tree.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/swap.h>
@@ -687,8 +688,9 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
        unsigned long new_start = old_start - shift;
        unsigned long new_end = old_end - shift;
        VMA_ITERATOR(vmi, mm, new_start);
-       struct vm_area_struct *next;
+       struct vm_area_struct *next, *new_vma;
        struct mmu_gather tlb;
+       MA_STATE(mas, &mm->mm_mt, new_start, new_start);
 
        BUG_ON(new_start > new_end);
 
@@ -699,10 +701,12 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
        if (vma != vma_next(&vmi))
                return -EFAULT;
 
+       if (mas_preallocate(&mas, vma, GFP_KERNEL))
+               return -ENOMEM;
        /*
         * cover the whole range: [new_start, old_end)
         */
-       if (vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL))
+       if (vma_expand(&mas, vma, new_start, old_end, vma->vm_pgoff, vma))
                return -ENOMEM;
 
        /*
@@ -711,7 +715,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
         */
        if (length != move_page_tables(vma, old_start,
                                       vma, new_start, length, false))
-               return -ENOMEM;
+               goto pt_move_failed;
 
        lru_add_drain();
        tlb_gather_mmu(&tlb, mm);
@@ -734,12 +738,22 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
        }
        tlb_finish_mmu(&tlb);
 
+       if (sub_vma(mm, vma, &new_vma, new_start, new_end))
+               goto sub_vma_failed;
+
        /*
         * Shrink the vma to just the new range.  Always succeeds.
         */
-       vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL);
+       vma_mas_store(new_vma, &mas);
+       vma_mas_szero(&mas, new_end, old_end);
 
        return 0;
+
+sub_vma_failed:
+pt_move_failed:
+       mas_destroy(&mas);
+
+       return -ENOMEM;
 }
 
 /*
index d0422f62b876e9b90437249cbd01e77c651049f2..c12afba3e5f9701e4c3afc0e2154a771ffa9c05f 100644 (file)
@@ -2645,6 +2645,15 @@ void anon_vma_interval_tree_verify(struct anon_vma_chain *node);
 extern int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin);
 extern int vma_adjust(struct vm_area_struct *vma, unsigned long start,
              unsigned long end, pgoff_t pgoff, struct vm_area_struct *expand);
+inline int vma_expand(struct ma_state *mas, struct vm_area_struct *vma,
+                     unsigned long start, unsigned long end, pgoff_t pgoff,
+                     struct vm_area_struct *next);
+inline void vma_mas_szero(struct ma_state *mas, unsigned long start,
+                               unsigned long end);
+inline void vma_mas_store(struct vm_area_struct *vma, struct ma_state *mas);
+int sub_vma(struct mm_struct *mm, struct vm_area_struct *vma,
+       struct vm_area_struct **new_vma, unsigned long start, unsigned long end);
+
 extern struct vm_area_struct *vma_merge(struct mm_struct *,
        struct vm_area_struct *prev, unsigned long addr, unsigned long end,
        unsigned long vm_flags, struct anon_vma *, struct file *, pgoff_t,
index d4a0716b926dbf0fb446714ee4e1ef2c191bc1a9..a01eec04d4c19a9ea73f09f307b6d69b13ddc076 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -507,7 +507,7 @@ void vma_mas_remove(struct vm_area_struct *vma, struct ma_state *mas)
  * @start: The start address to zero
  * @end: The end address to zero.
  */
-static inline void vma_mas_szero(struct ma_state *mas, unsigned long start,
+inline void vma_mas_szero(struct ma_state *mas, unsigned long start,
                                unsigned long end)
 {
        trace_vma_mas_szero(mas->tree, start, end - 1);