Commit e49e76c2 authored by Lorenzo Stoakes's avatar Lorenzo Stoakes Committed by Andrew Morton
Browse files

mm/mremap: cleanup post-processing stage of mremap

Separate out the uffd bits so it clear's what's happening.

Don't bother setting vrm->mmap_locked after unlocking, because after this
we are done anyway.

The only time we drop the mmap lock is on VMA shrink, at which point
vrm->new_len will be < vrm->old_len and the operation will not be
performed anyway, so move this code out of the if (vrm->mmap_locked)
block.

All addresses returned by mremap() are page-aligned, so the
offset_in_page() check on ret seems only to be incorrectly trying to
detect whether an error occurred - explicitly check for this.

No functional change intended.

Link: https://lkml.kernel.org/r/ebb8f29650b8e343fe98fefc67b3a61a24d1e0f1.1752770784.git.lorenzo.stoakes@oracle.com


Signed-off-by: default avatarLorenzo Stoakes <lorenzo.stoakes@oracle.com>
Reviewed-by: default avatarVlastimil Babka <vbabka@suse.cz>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Jann Horn <jannh@google.com>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Rik van Riel <riel@surriel.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent f256a7a4
Loading
Loading
Loading
Loading
+13 −9
Original line number Diff line number Diff line
@@ -1729,6 +1729,15 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
	return 0;
}

static void notify_uffd(struct vma_remap_struct *vrm, unsigned long to)
{
	struct mm_struct *mm = current->mm;

	userfaultfd_unmap_complete(mm, vrm->uf_unmap_early);
	mremap_userfaultfd_complete(vrm->uf, vrm->addr, to, vrm->old_len);
	userfaultfd_unmap_complete(mm, vrm->uf_unmap);
}

static unsigned long do_mremap(struct vma_remap_struct *vrm)
{
	struct mm_struct *mm = current->mm;
@@ -1754,18 +1763,13 @@ static unsigned long do_mremap(struct vma_remap_struct *vrm)
	res = vrm_implies_new_addr(vrm) ? mremap_to(vrm) : mremap_at(vrm);

out:
	if (vrm->mmap_locked) {
	if (vrm->mmap_locked)
		mmap_write_unlock(mm);
		vrm->mmap_locked = false;

		if (!offset_in_page(res) && vrm->mlocked && vrm->new_len > vrm->old_len)
	if (!IS_ERR_VALUE(res) && vrm->mlocked && vrm->new_len > vrm->old_len)
		mm_populate(vrm->new_addr + vrm->old_len, vrm->delta);
	}

	userfaultfd_unmap_complete(mm, vrm->uf_unmap_early);
	mremap_userfaultfd_complete(vrm->uf, vrm->addr, res, vrm->old_len);
	userfaultfd_unmap_complete(mm, vrm->uf_unmap);

	notify_uffd(vrm, res);
	return res;
}