The UFFDIO_MOVE ioctl's move_pages() loop splits a huge PMD when the
folio is pinned and can't be moved at PMD granularity.

If the split fails, the PMD stays huge and move_pages_pte() can't
process individual pages. Break out of the loop on split failure
and return -ENOMEM to the caller. This is similar to how other
allocation failures (__pte_alloc, mm_alloc_pmd) are handled in
move_pages().

Signed-off-by: Usama Arif <[email protected]>
---
 mm/userfaultfd.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
index e19872e518785..2728102e00c72 100644
--- a/mm/userfaultfd.c
+++ b/mm/userfaultfd.c
@@ -1870,7 +1870,13 @@ ssize_t move_pages(struct userfaultfd_ctx *ctx, unsigned 
long dst_start,
                                }
 
                                spin_unlock(ptl);
-                               split_huge_pmd(src_vma, src_pmd, src_addr);
+                               /*
+                                * If split fails, the PMD stays huge and
+                                * move_pages_pte can't process it.
+                                */
+                               err = split_huge_pmd(src_vma, src_pmd, 
src_addr);
+                               if (err)
+                                       break;
                                /* The folio will be split by move_pages_pte() 
*/
                                continue;
                        }
-- 
2.47.3


Reply via email to