@@ -567,11 +567,11 @@ static int vma_link(struct mm_struct *mm, struct vm_area_struct *vma,
567
567
* mm's list and the mm tree. It has already been inserted into the interval tree.
568
568
*/
569
569
static void __insert_vm_struct (struct mm_struct * mm , struct ma_state * mas ,
570
- struct vm_area_struct * vma )
570
+ struct vm_area_struct * vma , unsigned long location )
571
571
{
572
572
struct vm_area_struct * prev ;
573
573
574
- mas_set (mas , vma -> vm_start );
574
+ mas_set (mas , location );
575
575
prev = mas_prev (mas , 0 );
576
576
vma_mas_store (vma , mas );
577
577
__vma_link_list (mm , vma , prev );
@@ -601,6 +601,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
601
601
int remove_next = 0 ;
602
602
MA_STATE (mas , & mm -> mm_mt , 0 , 0 );
603
603
struct vm_area_struct * exporter = NULL , * importer = NULL ;
604
+ unsigned long ll_prev = vma -> vm_start ; /* linked list prev. */
604
605
605
606
if (next && !insert ) {
606
607
if (end >= next -> vm_end ) {
@@ -728,15 +729,27 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
728
729
}
729
730
730
731
if (start != vma -> vm_start ) {
731
- if (vma -> vm_start < start )
732
+ if ((vma -> vm_start < start ) &&
733
+ (!insert || (insert -> vm_end != start ))) {
732
734
vma_mas_szero (& mas , vma -> vm_start , start );
733
- vma_changed = true;
735
+ VM_WARN_ON (insert && insert -> vm_start > vma -> vm_start );
736
+ } else {
737
+ vma_changed = true;
738
+ }
734
739
vma -> vm_start = start ;
735
740
}
736
741
if (end != vma -> vm_end ) {
737
- if (vma -> vm_end > end )
738
- vma_mas_szero (& mas , end , vma -> vm_end );
739
- vma_changed = true;
742
+ if (vma -> vm_end > end ) {
743
+ if (!insert || (insert -> vm_start != end )) {
744
+ vma_mas_szero (& mas , end , vma -> vm_end );
745
+ VM_WARN_ON (insert &&
746
+ insert -> vm_end < vma -> vm_end );
747
+ } else if (insert -> vm_start == end ) {
748
+ ll_prev = vma -> vm_end ;
749
+ }
750
+ } else {
751
+ vma_changed = true;
752
+ }
740
753
vma -> vm_end = end ;
741
754
if (!next )
742
755
mm -> highest_vm_end = vm_end_gap (vma );
@@ -783,7 +796,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
783
796
* us to insert it before dropping the locks
784
797
* (it may either follow vma or precede it).
785
798
*/
786
- __insert_vm_struct (mm , & mas , insert );
799
+ __insert_vm_struct (mm , & mas , insert , ll_prev );
787
800
}
788
801
789
802
if (anon_vma ) {
@@ -870,6 +883,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
870
883
if (insert && file )
871
884
uprobe_mmap (insert );
872
885
886
+ mas_destroy (& mas );
873
887
validate_mm (mm );
874
888
return 0 ;
875
889
}
0 commit comments