From aede79b81ecd09d5f505f4b440b787c07f600a22 Mon Sep 17 00:00:00 2001 From: "Liam R. Howlett" Date: Mon, 1 May 2023 20:27:52 -0400 Subject: [PATCH] ANDROID: mm: Fix __vma_adjust() writes for the maple tree 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 Link: http://git.infradead.org/users/jedix/linux-maple.git/commit/61b337f6508fb566553f204a69e743524730e860 [surenb: __vma_adjust was removed in 6.3, therefore these fixes are not applicable upstream anymore. The patch was obtained from the author's tree] Bug: 274059236 Change-Id: I69d68a5b4ff11c40985f7b03b31eec4bb24dcbb6 Signed-off-by: Suren Baghdasaryan --- mm/mmap.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 0d33dc1056f5..5ff6be2faac4 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -715,6 +715,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; @@ -759,24 +766,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;