From: Liam R. Howlett <Liam.Howlett@oracle.com> Date: Tue, 9 Aug 2022 20:25:02 +0000 (-0400) Subject: mm/mmap: Introduce init_vma_lock() X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=8895bea61d587f4544a47ebd6dca107e0c34e85f;p=users%2Fjedix%2Flinux-maple.git mm/mmap: Introduce init_vma_lock() Add init_vma_lock() to set up the struct vma_locking. This is to abstract the locking when adjusting VMAs. Also remove the use of remove_next int in favour of a pointer to the VMA to remove. Rename next_next to remove2 since this better reflects its use. Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com> --- diff --git a/mm/mmap.c b/mm/mmap.c index 0a787531e3fc..8d8ef8c08b5c 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -493,6 +493,40 @@ static int vma_link(struct mm_struct *mm, struct vm_area_struct *vma) return 0; } +/* + * init_multi_vma_lock() - Initializer for struct vma_locking + * @vl: The vma_locking struct + * @vma: The vma that will be altered once locked + * @next: The next vma if it is to be adjusted + * @remove: The first vma to be removed + * @remove2: The second vma to be removed + */ +static inline void init_multi_vma_lock(struct vma_locking *vl, + struct vm_area_struct *vma, struct vm_area_struct *next, + struct vm_area_struct *remove, struct vm_area_struct *remove2) +{ + + memset(vl, 0, sizeof(struct vma_locking)); + vl->vma = vma; + vl->anon_vma = vma->anon_vma; + vl->remove = remove; + vl->remove2 = remove2; + vl->adj_next = next; + if (!vl->anon_vma && next) + vl->anon_vma = next->anon_vma; + + vl->file = vma->vm_file; + if (vl->file) + vl->mapping = vma->vm_file->f_mapping; + +} + +static inline void init_vma_lock(struct vma_locking *vl, + struct vm_area_struct *vma) +{ + init_multi_vma_lock(vl, vma, NULL, NULL, NULL); +} + /* * lock_vma() - Helper function for locking VMAs prior to altering * @vl: The initialized vma_locking struct @@ -601,7 +635,7 @@ again: /* * In mprotect's case 6 (see comments on vma_merge), - * we must remove next_next too. + * we must remove the one after next too. */ if (vl->remove2) { vl->remove = vl->remove2; @@ -635,17 +669,14 @@ inline int vma_expand(struct ma_state *mas, struct vm_area_struct *vma, struct vm_area_struct *next) { + bool remove_next = false; struct vma_locking vma_lock; - memset(&vma_lock, 0, sizeof(vma_lock)); - vma_lock.vma = vma; - vma_lock.anon_vma = vma->anon_vma; if (next && (vma != next) && (end == next->vm_end)) { - vma_lock.remove = next; + remove_next = true; if (next->anon_vma && !vma->anon_vma) { int error; - vma_lock.anon_vma = next->anon_vma; vma->anon_vma = next->anon_vma; error = anon_vma_clone(vma, next); if (error) @@ -653,6 +684,8 @@ inline int vma_expand(struct ma_state *mas, struct vm_area_struct *vma, } } + init_multi_vma_lock(&vma_lock, vma, NULL, remove_next ? next : NULL, + NULL); /* Not merging but overwriting any part of next is not handled. */ VM_BUG_ON(next && !vma_lock.remove && next != vma && end > next->vm_start); @@ -663,10 +696,6 @@ inline int vma_expand(struct ma_state *mas, struct vm_area_struct *vma, goto nomem; vma_adjust_trans_huge(vma, start, end, 0); - - vma_lock.file = vma->vm_file; - if (vma_lock.file) - vma_lock.mapping = vma_lock.file->f_mapping; lock_vma(&vma_lock); vma->vm_start = start; @@ -682,6 +711,7 @@ inline int vma_expand(struct ma_state *mas, struct vm_area_struct *vma, nomem: return -ENOMEM; } + /* * We cannot adjust vm_start, vm_end, vm_pgoff fields of a vma that * is already present in an i_mmap tree without adjusting the tree. @@ -694,14 +724,13 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, struct vm_area_struct *expand) { struct mm_struct *mm = vma->vm_mm; - struct vm_area_struct *next_next = NULL; + struct vm_area_struct *remove2 = NULL; + struct vm_area_struct *remove = NULL; struct vm_area_struct *next = find_vma(mm, vma->vm_end); struct vm_area_struct *orig_vma = vma; - struct anon_vma *anon_vma = NULL; struct file *file = vma->vm_file; bool vma_changed = false; long adjust_next = 0; - int remove_next = 0; MA_STATE(mas, &mm->mm_mt, 0, 0); struct vm_area_struct *exporter = NULL, *importer = NULL; struct vma_locking vma_lock; @@ -725,21 +754,21 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, * removing "vma" and that to do so we * swapped "vma" and "next". */ - remove_next = 3; VM_WARN_ON(file != next->vm_file); swap(vma, next); + remove = next; } else { VM_WARN_ON(expand != vma); /* * case 1, 6, 7, remove_next == 2 is case 6, * remove_next == 1 is case 1 or 7. */ - remove_next = 1 + (end > next->vm_end); - if (remove_next == 2) - next_next = find_vma(mm, next->vm_end); + remove = next; + if (end > next->vm_end); + remove2 = find_vma(mm, next->vm_end); - VM_WARN_ON(remove_next == 2 && - end != next_next->vm_end); + VM_WARN_ON(remove2 != NULL && + end != remove2->vm_end); } exporter = next; @@ -749,8 +778,8 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, * If next doesn't have anon_vma, import from vma after * next, if the vma overlaps with it. */ - if (remove_next == 2 && !next->anon_vma) - exporter = next_next; + if (remove2 != NULL && !next->anon_vma) + exporter = remove2; } else if (end > next->vm_start) { /* @@ -791,30 +820,14 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, if (mas_preallocate(&mas, vma, GFP_KERNEL)) return -ENOMEM; - anon_vma = vma->anon_vma; - if (!anon_vma && adjust_next) - anon_vma = next->anon_vma; - - if (anon_vma) - VM_WARN_ON(adjust_next && next->anon_vma && - anon_vma != next->anon_vma); - vma_adjust_trans_huge(orig_vma, start, end, adjust_next); - memset(&vma_lock, 0, sizeof(vma_lock)); - vma_lock.vma = vma; - vma_lock.anon_vma = anon_vma; - vma_lock.file = file; - if (adjust_next) - vma_lock.adj_next = next; - if (file) - vma_lock.mapping = file->f_mapping; - vma_lock.insert = insert; - if (remove_next) { - vma_lock.remove = next; - vma_lock.remove2 = next_next; - } + init_multi_vma_lock(&vma_lock, vma, adjust_next ? next : NULL, remove, + remove2); + VM_WARN_ON(vma_lock.anon_vma && adjust_next && next->anon_vma && + vma_lock.anon_vma != next->anon_vma); + vma_lock.insert = insert; lock_vma(&vma_lock); if (start != vma->vm_start) {