struct anon_vma_name *anon_name)
 {
        pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
-       struct vm_area_struct *area, *next;
-       int err;
+       struct vm_area_struct *mid, *next, *res;
+       int err = -1;
+       bool merge_prev = false;
+       bool merge_next = false;
 
        /*
         * We later require that vma->vm_flags == vm_flags,
                return NULL;
 
        next = find_vma(mm, prev ? prev->vm_end : 0);
-       area = next;
-       if (area && area->vm_end == end)                /* cases 6, 7, 8 */
+       mid = next;
+       if (next && next->vm_end == end)                /* cases 6, 7, 8 */
                next = find_vma(mm, next->vm_end);
 
        /* verify some invariant that must be enforced by the caller */
        VM_WARN_ON(prev && addr <= prev->vm_start);
-       VM_WARN_ON(area && end > area->vm_end);
+       VM_WARN_ON(mid && end > mid->vm_end);
        VM_WARN_ON(addr >= end);
 
-       /*
-        * Can it merge with the predecessor?
-        */
+       /* Can we merge the predecessor? */
        if (prev && prev->vm_end == addr &&
                        mpol_equal(vma_policy(prev), policy) &&
                        can_vma_merge_after(prev, vm_flags,
                                            anon_vma, file, pgoff,
                                            vm_userfaultfd_ctx, anon_name)) {
-               /*
-                * OK, it can.  Can we now merge in the successor as well?
-                */
-               if (next && end == next->vm_start &&
-                               mpol_equal(policy, vma_policy(next)) &&
-                               can_vma_merge_before(next, vm_flags,
-                                                    anon_vma, file,
-                                                    pgoff+pglen,
-                                                    vm_userfaultfd_ctx, anon_name) &&
-                               is_mergeable_anon_vma(prev->anon_vma,
-                                                     next->anon_vma, NULL)) {
-                                                       /* cases 1, 6 */
-                       err = __vma_adjust(prev, prev->vm_start,
-                                        next->vm_end, prev->vm_pgoff, NULL,
-                                        prev);
-               } else                                  /* cases 2, 5, 7 */
-                       err = __vma_adjust(prev, prev->vm_start,
-                                        end, prev->vm_pgoff, NULL, prev);
-               if (err)
-                       return NULL;
-               khugepaged_enter_vma(prev, vm_flags);
-               return prev;
+               merge_prev = true;
        }
-
-       /*
-        * Can this new request be merged in front of next?
-        */
+       /* Can we merge the successor? */
        if (next && end == next->vm_start &&
                        mpol_equal(policy, vma_policy(next)) &&
                        can_vma_merge_before(next, vm_flags,
                                             anon_vma, file, pgoff+pglen,
                                             vm_userfaultfd_ctx, anon_name)) {
+               merge_next = true;
+       }
+       /* Can we merge both the predecessor and the successor? */
+       if (merge_prev && merge_next &&
+                       is_mergeable_anon_vma(prev->anon_vma,
+                               next->anon_vma, NULL)) {         /* cases 1, 6 */
+               err = __vma_adjust(prev, prev->vm_start,
+                                       next->vm_end, prev->vm_pgoff, NULL,
+                                       prev);
+               res = prev;
+       } else if (merge_prev) {                        /* cases 2, 5, 7 */
+               err = __vma_adjust(prev, prev->vm_start,
+                                       end, prev->vm_pgoff, NULL, prev);
+               res = prev;
+       } else if (merge_next) {
                if (prev && addr < prev->vm_end)        /* case 4 */
                        err = __vma_adjust(prev, prev->vm_start,
-                                        addr, prev->vm_pgoff, NULL, next);
-               else {                                  /* cases 3, 8 */
-                       err = __vma_adjust(area, addr, next->vm_end,
-                                        next->vm_pgoff - pglen, NULL, next);
-                       /*
-                        * In case 3 area is already equal to next and
-                        * this is a noop, but in case 8 "area" has
-                        * been removed and next was expanded over it.
-                        */
-                       area = next;
-               }
-               if (err)
-                       return NULL;
-               khugepaged_enter_vma(area, vm_flags);
-               return area;
+                                       addr, prev->vm_pgoff, NULL, next);
+               else                                    /* cases 3, 8 */
+                       err = __vma_adjust(mid, addr, next->vm_end,
+                                       next->vm_pgoff - pglen, NULL, next);
+               res = next;
        }
 
-       return NULL;
+       /*
+        * Cannot merge with predecessor or successor or error in __vma_adjust?
+        */
+       if (err)
+               return NULL;
+       khugepaged_enter_vma(res, vm_flags);
+       return res;
 }
 
 /*