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.

Signed-off-by: Lorenzo Stoakes <lorenzo.stoa...@oracle.com>
Reviewed-by: Vlastimil Babka <vba...@suse.cz>
---
 mm/mremap.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/mm/mremap.c b/mm/mremap.c
index d57645573e0d..87cab223f2bb 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -1731,6 +1731,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;
@@ -1756,18 +1765,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)
-                       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);
+       if (!IS_ERR_VALUE(res) && vrm->mlocked && vrm->new_len > vrm->old_len)
+               mm_populate(vrm->new_addr + vrm->old_len, vrm->delta);
 
+       notify_uffd(vrm, res);
        return res;
 }
 
-- 
2.50.0


Reply via email to