On expansion failure, we try to restore vmg state, but we missed to restore vmi.index. The reason is we have reset vmg->vma before checking. So let's put the operation before reset vmg->vma. Also we don't need to do the restore if there is no mergeable adjacent VMA. Let's take it out to skip the unnecessary operations. Signed-off-by: Wei Yang <richard.weiyang@xxxxxxxxx> CC: Lorenzo Stoakes <lorenzo.stoakes@xxxxxxxxxx> --- mm/vma.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mm/vma.c b/mm/vma.c index fb4f1863f88e..c94d953d453c 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -954,23 +954,27 @@ struct vm_area_struct *vma_merge_new_range(struct vma_merge_struct *vmg) vma_prev(vmg->vmi); /* Equivalent to going to the previous range */ } + /* No mergeable adjacent VMA, return */ + if (!vmg->vma) + return NULL; + /* * Now try to expand adjacent VMA(s). This takes care of removing the * following VMA if we have VMAs on both sides. */ - if (vmg->vma && !vma_expand(vmg)) { + if (!vma_expand(vmg)) { khugepaged_enter_vma(vmg->vma, vmg->flags); vmg->state = VMA_MERGE_SUCCESS; return vmg->vma; } /* If expansion failed, reset state. Allows us to retry merge later. */ + if (vmg->vma == prev) + vma_iter_set(vmg->vmi, start); vmg->vma = NULL; vmg->start = start; vmg->end = end; vmg->pgoff = pgoff; - if (vmg->vma == prev) - vma_iter_set(vmg->vmi, start); return NULL; } -- 2.34.1