vma.c (25d3925fa51ddeec9d5a2c9b89140f5218ec3ef4) vma.c (65e0aa64df916861ad8579e23f885e56e5ec8647)
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3/*
4 * VMA-specific functions.
5 */
6
7#include "vma_internal.h"
8#include "vma.h"

--- 571 unchanged lines hidden (view full) ---

580 if (i != mm->map_count) {
581 pr_emerg("map_count %d vma iterator %d\n", mm->map_count, i);
582 bug = 1;
583 }
584 VM_BUG_ON_MM(bug, mm);
585}
586#endif /* CONFIG_DEBUG_VM_MAPLE_TREE */
587
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3/*
4 * VMA-specific functions.
5 */
6
7#include "vma_internal.h"
8#include "vma.h"

--- 571 unchanged lines hidden (view full) ---

580 if (i != mm->map_count) {
581 pr_emerg("map_count %d vma iterator %d\n", mm->map_count, i);
582 bug = 1;
583 }
584 VM_BUG_ON_MM(bug, mm);
585}
586#endif /* CONFIG_DEBUG_VM_MAPLE_TREE */
587
588/* Actually perform the VMA merge operation. */
589static int commit_merge(struct vma_merge_struct *vmg,
590 struct vm_area_struct *remove)
591{
592 struct vma_prepare vp;
593
594 init_multi_vma_prep(&vp, vmg->vma, NULL, remove, NULL);
595
596 /* Note: vma iterator must be pointing to 'start'. */
597 vma_iter_config(vmg->vmi, vmg->start, vmg->end);
598
599 if (vma_iter_prealloc(vmg->vmi, vmg->vma))
600 return -ENOMEM;
601
602 vma_prepare(&vp);
603 vma_adjust_trans_huge(vmg->vma, vmg->start, vmg->end, 0);
604 vma_set_range(vmg->vma, vmg->start, vmg->end, vmg->pgoff);
605
606 vma_iter_store(vmg->vmi, vmg->vma);
607
608 vma_complete(&vp, vmg->vmi, vmg->vma->vm_mm);
609
610 return 0;
611}
612
588/*
589 * vma_merge_new_range - Attempt to merge a new VMA into address space
590 *
591 * @vmg: Describes the VMA we are adding, in the range @vmg->start to @vmg->end
592 * (exclusive), which we try to merge with any adjacent VMAs if possible.
593 *
594 * We are about to add a VMA to the address space starting at @vmg->start and
595 * ending at @vmg->end. There are three different possible scenarios:

--- 111 unchanged lines hidden (view full) ---

707 * - The caller must have set @vmg->vma and @vmg->next.
708 */
709int vma_expand(struct vma_merge_struct *vmg)
710{
711 struct vm_area_struct *anon_dup = NULL;
712 bool remove_next = false;
713 struct vm_area_struct *vma = vmg->vma;
714 struct vm_area_struct *next = vmg->next;
613/*
614 * vma_merge_new_range - Attempt to merge a new VMA into address space
615 *
616 * @vmg: Describes the VMA we are adding, in the range @vmg->start to @vmg->end
617 * (exclusive), which we try to merge with any adjacent VMAs if possible.
618 *
619 * We are about to add a VMA to the address space starting at @vmg->start and
620 * ending at @vmg->end. There are three different possible scenarios:

--- 111 unchanged lines hidden (view full) ---

732 * - The caller must have set @vmg->vma and @vmg->next.
733 */
734int vma_expand(struct vma_merge_struct *vmg)
735{
736 struct vm_area_struct *anon_dup = NULL;
737 bool remove_next = false;
738 struct vm_area_struct *vma = vmg->vma;
739 struct vm_area_struct *next = vmg->next;
715 struct vma_prepare vp;
716
717 mmap_assert_write_locked(vmg->mm);
718
719 vma_start_write(vma);
720 if (next && (vma != next) && (vmg->end == next->vm_end)) {
721 int ret;
722
723 remove_next = true;
724 vma_start_write(next);
725 ret = dup_anon_vma(vma, next, &anon_dup);
726 if (ret)
727 return ret;
728 }
729
740
741 mmap_assert_write_locked(vmg->mm);
742
743 vma_start_write(vma);
744 if (next && (vma != next) && (vmg->end == next->vm_end)) {
745 int ret;
746
747 remove_next = true;
748 vma_start_write(next);
749 ret = dup_anon_vma(vma, next, &anon_dup);
750 if (ret)
751 return ret;
752 }
753
730 init_multi_vma_prep(&vp, vma, NULL, remove_next ? next : NULL, NULL);
731 /* Not merging but overwriting any part of next is not handled. */
754 /* Not merging but overwriting any part of next is not handled. */
732 VM_WARN_ON(next && !vp.remove &&
755 VM_WARN_ON(next && !remove_next &&
733 next != vma && vmg->end > next->vm_start);
734 /* Only handles expanding */
735 VM_WARN_ON(vma->vm_start < vmg->start || vma->vm_end > vmg->end);
736
756 next != vma && vmg->end > next->vm_start);
757 /* Only handles expanding */
758 VM_WARN_ON(vma->vm_start < vmg->start || vma->vm_end > vmg->end);
759
737 /* Note: vma iterator must be pointing to 'start' */
738 vma_iter_config(vmg->vmi, vmg->start, vmg->end);
739 if (vma_iter_prealloc(vmg->vmi, vma))
760 if (commit_merge(vmg, remove_next ? next : NULL))
740 goto nomem;
741
761 goto nomem;
762
742 vma_prepare(&vp);
743 vma_adjust_trans_huge(vma, vmg->start, vmg->end, 0);
744 vma_set_range(vma, vmg->start, vmg->end, vmg->pgoff);
745 vma_iter_store(vmg->vmi, vma);
746
747 vma_complete(&vp, vmg->vmi, vma->vm_mm);
748 return 0;
749
750nomem:
751 vmg->state = VMA_MERGE_ERROR_NOMEM;
752 if (anon_dup)
753 unlink_anon_vmas(anon_dup);
754 return -ENOMEM;
755}

--- 1271 unchanged lines hidden ---
763 return 0;
764
765nomem:
766 vmg->state = VMA_MERGE_ERROR_NOMEM;
767 if (anon_dup)
768 unlink_anon_vmas(anon_dup);
769 return -ENOMEM;
770}

--- 1271 unchanged lines hidden ---