struct ma_state mas_detach;
        struct maple_tree mt_detach;
        unsigned long end = addr + len;
-       unsigned long merge_start = addr, merge_end = end;
        bool writable_file_mapping = false;
        int error = -ENOMEM;
        VMA_ITERATOR(vmi, mm, addr);
        /* Attempt to expand an old mapping */
        /* Check next */
        if (next && next->vm_start == end && can_vma_merge_before(&vmg)) {
-               merge_end = next->vm_end;
-               vma = next;
+               vmg.end = next->vm_end;
+               vma = vmg.vma = next;
                vmg.pgoff = next->vm_pgoff - pglen;
                /*
                 * We set this here so if we will merge with the previous VMA in
 
        /* Check prev */
        if (prev && prev->vm_end == addr && can_vma_merge_after(&vmg)) {
-               merge_start = prev->vm_start;
-               vma = prev;
+               vmg.start = prev->vm_start;
+               vma = vmg.vma = prev;
                vmg.pgoff = prev->vm_pgoff;
                vma_prev(&vmi); /* Equivalent to going to the previous range */
        }
 
        if (vma) {
                /* Actually expand, if possible */
-               if (!vma_expand(&vmi, vma, merge_start, merge_end, vmg.pgoff, next)) {
+               if (!vma_expand(&vmg)) {
                        khugepaged_enter_vma(vma, vm_flags);
                        goto expanded;
                }
        unsigned long new_start = old_start - shift;
        unsigned long new_end = old_end - shift;
        VMA_ITERATOR(vmi, mm, new_start);
+       VMG_STATE(vmg, mm, &vmi, new_start, old_end, 0, vma->vm_pgoff);
        struct vm_area_struct *next;
        struct mmu_gather tlb;
 
        /*
         * cover the whole range: [new_start, old_end)
         */
-       if (vma_expand(&vmi, vma, new_start, old_end, vma->vm_pgoff, NULL))
+       vmg.vma = vma;
+       if (vma_expand(&vmg))
                return -ENOMEM;
 
        /*
 
 /*
  * vma_expand - Expand an existing VMA
  *
- * @vmi: The vma iterator
- * @vma: The vma to expand
- * @start: The start of the vma
- * @end: The exclusive end of the vma
- * @pgoff: The page offset of vma
- * @next: The current of next vma.
+ * @vmg: Describes a VMA expansion operation.
  *
- * Expand @vma to @start and @end.  Can expand off the start and end.  Will
- * expand over @next if it's different from @vma and @end == @next->vm_end.
- * Checking if the @vma can expand and merge with @next needs to be handled by
- * the caller.
+ * Expand @vma to vmg->start and vmg->end.  Can expand off the start and end.
+ * Will expand over vmg->next if it's different from vmg->vma and vmg->end ==
+ * vmg->next->vm_end.  Checking if the vmg->vma can expand and merge with
+ * vmg->next needs to be handled by the caller.
  *
  * Returns: 0 on success
  */
-int vma_expand(struct vma_iterator *vmi, struct vm_area_struct *vma,
-              unsigned long start, unsigned long end, pgoff_t pgoff,
-              struct vm_area_struct *next)
+int vma_expand(struct vma_merge_struct *vmg)
 {
        struct vm_area_struct *anon_dup = NULL;
        bool remove_next = false;
+       struct vm_area_struct *vma = vmg->vma;
+       struct vm_area_struct *next = vmg->next;
        struct vma_prepare vp;
 
        vma_start_write(vma);
-       if (next && (vma != next) && (end == next->vm_end)) {
+       if (next && (vma != next) && (vmg->end == next->vm_end)) {
                int ret;
 
                remove_next = true;
        init_multi_vma_prep(&vp, vma, NULL, remove_next ? next : NULL, NULL);
        /* Not merging but overwriting any part of next is not handled. */
        VM_WARN_ON(next && !vp.remove &&
-                 next != vma && end > next->vm_start);
+                 next != vma && vmg->end > next->vm_start);
        /* Only handles expanding */
-       VM_WARN_ON(vma->vm_start < start || vma->vm_end > end);
+       VM_WARN_ON(vma->vm_start < vmg->start || vma->vm_end > vmg->end);
 
        /* Note: vma iterator must be pointing to 'start' */
-       vma_iter_config(vmi, start, end);
-       if (vma_iter_prealloc(vmi, vma))
+       vma_iter_config(vmg->vmi, vmg->start, vmg->end);
+       if (vma_iter_prealloc(vmg->vmi, vma))
                goto nomem;
 
        vma_prepare(&vp);
-       vma_adjust_trans_huge(vma, start, end, 0);
-       vma_set_range(vma, start, end, pgoff);
-       vma_iter_store(vmi, vma);
+       vma_adjust_trans_huge(vma, vmg->start, vmg->end, 0);
+       vma_set_range(vma, vmg->start, vmg->end, vmg->pgoff);
+       vma_iter_store(vmg->vmi, vma);
 
-       vma_complete(&vp, vmi, vma->vm_mm);
+       vma_complete(&vp, vmg->vmi, vma->vm_mm);
        return 0;
 
 nomem:
 
 void vma_complete(struct vma_prepare *vp,
                  struct vma_iterator *vmi, struct mm_struct *mm);
 
-int vma_expand(struct vma_iterator *vmi, struct vm_area_struct *vma,
-              unsigned long start, unsigned long end, pgoff_t pgoff,
-              struct vm_area_struct *next);
-
+int vma_expand(struct vma_merge_struct *vmg);
 int vma_shrink(struct vma_iterator *vmi, struct vm_area_struct *vma,
               unsigned long start, unsigned long end, pgoff_t pgoff);