--- x/mm/vma.c +++ y/mm/vma.c @@ -1263,11 +1263,12 @@ static void vms_complete_munmap_vmas(str mm = current->mm; mm->map_count -= vms->vma_count; mm->locked_vm -= vms->locked_vm; - if (vms->unlock) - mmap_write_downgrade(mm); - if (!vms->nr_pages) + if (!vms->nr_pages) { + if (vms->unlock) + mmap_write_unlock(mm); return; + } vms_clear_ptes(vms, mas_detach, !vms->unlock); /* Update high watermark before we lower total_vm */ @@ -1284,13 +1285,15 @@ static void vms_complete_munmap_vmas(str /* Remove and clean up vmas */ mas_set(mas_detach, 0); - mas_for_each(mas_detach, vma, ULONG_MAX) + mas_for_each(mas_detach, vma, ULONG_MAX) { + vma_start_write(vma); remove_vma(vma); + } vm_unacct_memory(vms->nr_accounted); validate_mm(mm); if (vms->unlock) - mmap_read_unlock(mm); + mmap_write_unlock(mm); __mt_destroy(mas_detach->tree); }