|
|
@@ -152,6 +152,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
|
|
|
new_ptl = pte_lockptr(mm, new_pmd);
|
|
|
if (new_ptl != old_ptl)
|
|
|
spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING);
|
|
|
+ flush_tlb_batched_pending(vma->vm_mm);
|
|
|
arch_enter_lazy_mmu_mode();
|
|
|
|
|
|
for (; old_addr < old_end; old_pte++, old_addr += PAGE_SIZE,
|
|
|
@@ -428,6 +429,7 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr,
|
|
|
static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
|
|
|
unsigned long new_addr, unsigned long new_len, bool *locked,
|
|
|
struct vm_userfaultfd_ctx *uf,
|
|
|
+ struct list_head *uf_unmap_early,
|
|
|
struct list_head *uf_unmap)
|
|
|
{
|
|
|
struct mm_struct *mm = current->mm;
|
|
|
@@ -446,7 +448,7 @@ static unsigned long mremap_to(unsigned long addr, unsigned long old_len,
|
|
|
if (addr + old_len > new_addr && new_addr + new_len > addr)
|
|
|
goto out;
|
|
|
|
|
|
- ret = do_munmap(mm, new_addr, new_len, NULL);
|
|
|
+ ret = do_munmap(mm, new_addr, new_len, uf_unmap_early);
|
|
|
if (ret)
|
|
|
goto out;
|
|
|
|
|
|
@@ -514,6 +516,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
|
|
|
unsigned long charged = 0;
|
|
|
bool locked = false;
|
|
|
struct vm_userfaultfd_ctx uf = NULL_VM_UFFD_CTX;
|
|
|
+ LIST_HEAD(uf_unmap_early);
|
|
|
LIST_HEAD(uf_unmap);
|
|
|
|
|
|
if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
|
|
|
@@ -541,7 +544,7 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
|
|
|
|
|
|
if (flags & MREMAP_FIXED) {
|
|
|
ret = mremap_to(addr, old_len, new_addr, new_len,
|
|
|
- &locked, &uf, &uf_unmap);
|
|
|
+ &locked, &uf, &uf_unmap_early, &uf_unmap);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
@@ -621,6 +624,7 @@ out:
|
|
|
up_write(¤t->mm->mmap_sem);
|
|
|
if (locked && new_len > old_len)
|
|
|
mm_populate(new_addr + old_len, new_len - old_len);
|
|
|
+ userfaultfd_unmap_complete(mm, &uf_unmap_early);
|
|
|
mremap_userfaultfd_complete(&uf, addr, new_addr, old_len);
|
|
|
userfaultfd_unmap_complete(mm, &uf_unmap);
|
|
|
return ret;
|