Skip to content

Commit 04241ff

Browse files
howlettakpm00
authored andcommitted
mm/mmap: introduce dup_vma_anon() helper
Create a helper for duplicating the anon vma when adjusting the vma. This simplifies the logic of __vma_adjust(). Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Liam R. Howlett <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent cf51e86 commit 04241ff

File tree

1 file changed

+40
-34
lines changed

1 file changed

+40
-34
lines changed

mm/mmap.c

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,29 @@ static inline void vma_complete(struct vma_prepare *vp,
617617
uprobe_mmap(vp->insert);
618618
}
619619

620+
/*
621+
* dup_anon_vma() - Helper function to duplicate anon_vma
622+
* @dst: The destination VMA
623+
* @src: The source VMA
624+
*
625+
* Returns: 0 on success.
626+
*/
627+
static inline int dup_anon_vma(struct vm_area_struct *dst,
628+
struct vm_area_struct *src)
629+
{
630+
/*
631+
* Easily overlooked: when mprotect shifts the boundary, make sure the
632+
* expanding vma has anon_vma set if the shrinking vma had, to cover any
633+
* anon pages imported.
634+
*/
635+
if (src->anon_vma && !dst->anon_vma) {
636+
dst->anon_vma = src->anon_vma;
637+
return anon_vma_clone(dst, src);
638+
}
639+
640+
return 0;
641+
}
642+
620643
/*
621644
* vma_expand - Expand an existing VMA
622645
*
@@ -642,15 +665,12 @@ int vma_expand(struct vma_iterator *vmi, struct vm_area_struct *vma,
642665
struct vma_prepare vp;
643666

644667
if (next && (vma != next) && (end == next->vm_end)) {
645-
remove_next = true;
646-
if (next->anon_vma && !vma->anon_vma) {
647-
int error;
668+
int ret;
648669

649-
vma->anon_vma = next->anon_vma;
650-
error = anon_vma_clone(vma, next);
651-
if (error)
652-
return error;
653-
}
670+
remove_next = true;
671+
ret = dup_anon_vma(vma, next);
672+
if (ret)
673+
return ret;
654674
}
655675

656676
init_multi_vma_prep(&vp, vma, NULL, remove_next ? next : NULL, NULL);
@@ -739,10 +759,11 @@ int __vma_adjust(struct vma_iterator *vmi, struct vm_area_struct *vma,
739759
struct file *file = vma->vm_file;
740760
bool vma_changed = false;
741761
long adjust_next = 0;
742-
struct vm_area_struct *exporter = NULL, *importer = NULL;
743762
struct vma_prepare vma_prep;
744763

745764
if (next) {
765+
int error = 0;
766+
746767
if (end >= next->vm_end) {
747768
/*
748769
* vma expands, overlapping all the next, and
@@ -777,50 +798,35 @@ int __vma_adjust(struct vma_iterator *vmi, struct vm_area_struct *vma,
777798
end != remove2->vm_end);
778799
}
779800

780-
exporter = next;
781-
importer = vma;
782-
783801
/*
784802
* If next doesn't have anon_vma, import from vma after
785803
* next, if the vma overlaps with it.
786804
*/
787-
if (remove2 != NULL && !next->anon_vma)
788-
exporter = remove2;
805+
if (remove != NULL && !next->anon_vma)
806+
error = dup_anon_vma(vma, remove2);
807+
else
808+
error = dup_anon_vma(vma, remove);
789809

790810
} else if (end > next->vm_start) {
791811
/*
792812
* vma expands, overlapping part of the next:
793813
* mprotect case 5 shifting the boundary up.
794814
*/
795815
adjust_next = (end - next->vm_start);
796-
exporter = next;
797-
importer = vma;
798-
VM_WARN_ON(expand != importer);
816+
VM_WARN_ON(expand != vma);
817+
error = dup_anon_vma(vma, next);
799818
} else if (end < vma->vm_end) {
800819
/*
801820
* vma shrinks, and !insert tells it's not
802821
* split_vma inserting another: so it must be
803822
* mprotect case 4 shifting the boundary down.
804823
*/
805824
adjust_next = -(vma->vm_end - end);
806-
exporter = vma;
807-
importer = next;
808-
VM_WARN_ON(expand != importer);
809-
}
810-
811-
/*
812-
* Easily overlooked: when mprotect shifts the boundary,
813-
* make sure the expanding vma has anon_vma set if the
814-
* shrinking vma had, to cover any anon pages imported.
815-
*/
816-
if (exporter && exporter->anon_vma && !importer->anon_vma) {
817-
int error;
818-
819-
importer->anon_vma = exporter->anon_vma;
820-
error = anon_vma_clone(importer, exporter);
821-
if (error)
822-
return error;
825+
VM_WARN_ON(expand != next);
826+
error = dup_anon_vma(next, vma);
823827
}
828+
if (error)
829+
return error;
824830
}
825831

826832
if (vma_iter_prealloc(vmi))

0 commit comments

Comments
 (0)