@@ -33,7 +33,51 @@ static bool test_copy_vma(void)
struct mm_struct mm = {};
bool need_locks = false;
VMA_ITERATOR(vmi, &mm, 0);
- struct vm_area_struct *vma, *vma_new, *vma_next;
+ struct vm_area_struct *vma, *vma_prev, *vma_new, *vma_next, *vma_orig;
+
+ /* Move forwards, adjacent to old self - self-merge. */
+
+ vma = alloc_and_link_vma(&mm, 0x1000, 0x2000, 1, vma_flags);
+ vma_set_anonymous(vma);
+ vma_orig = vma;
+ vma_new = copy_vma(&vma, 0x2000, 0x1000, 1, &need_locks);
+ ASSERT_EQ(vma_new, vma_orig);
+ ASSERT_EQ(vma, vma_orig);
+ ASSERT_EQ(vma_new->vm_start, 0x1000);
+ ASSERT_EQ(vma_new->vm_end, 0x3000);
+
+ cleanup_mm(&mm, &vmi);
+
+ /* Move backwards, adjacent to old self - self-merge. */
+
+ vma = alloc_and_link_vma(&mm, 0x2000, 0x3000, 2, vma_flags);
+ vma_set_anonymous(vma);
+ vma_orig = vma;
+ vma_new = copy_vma(&vma, 0x1000, 0x1000, 2, &need_locks);
+ ASSERT_EQ(vma_new, vma_orig);
+ ASSERT_EQ(vma, vma_orig);
+ ASSERT_EQ(vma_new->vm_start, 0x1000);
+ ASSERT_EQ(vma_new->vm_end, 0x3000);
+
+ cleanup_mm(&mm, &vmi);
+
+ /*
+ * Move backwards between prior VMA and old self - self-merge and vma
+ * updated to a new VMA.
+ */
+
+ vma_prev = alloc_and_link_vma(&mm, 0x1000, 0x2000, 1, vma_flags);
+ vma_set_anonymous(vma_prev);
+ vma = alloc_and_link_vma(&mm, 0x3000, 0x4000, 3, vma_flags);
+ vma_set_anonymous(vma);
+ vma_orig = vma;
+ vma_new = copy_vma(&vma, 0x2000, 0x1000, 3, &need_locks);
+ ASSERT_NE(vma_new, vma_orig);
+ ASSERT_EQ(vma_new, vma);
+ ASSERT_EQ(vma_new->vm_start, 0x1000);
+ ASSERT_EQ(vma_new->vm_end, 0x4000);
+
+ cleanup_mm(&mm, &vmi);
/* Move backwards and do not merge. */