@@ -294,6 +294,25 @@ static inline bool arch_supports_page_table_move(void)
294294}
295295#endif
296296
297+ static inline bool uffd_supports_page_table_move (struct pagetable_move_control * pmc )
298+ {
299+ /*
300+ * If we are moving a VMA that has uffd-wp registered but with
301+ * remap events disabled (new VMA will not be registered with uffd), we
302+ * need to ensure that the uffd-wp state is cleared from all pgtables.
303+ * This means recursing into lower page tables in move_page_tables().
304+ *
305+ * We might get called with VMAs reversed when recovering from a
306+ * failed page table move. In that case, the
307+ * "old"-but-actually-"originally new" VMA during recovery will not have
308+ * a uffd context. Recursing into lower page tables during the original
309+ * move but not during the recovery move will cause trouble, because we
310+ * run into already-existing page tables. So check both VMAs.
311+ */
312+ return !vma_has_uffd_without_event_remap (pmc -> old ) &&
313+ !vma_has_uffd_without_event_remap (pmc -> new );
314+ }
315+
297316#ifdef CONFIG_HAVE_MOVE_PMD
298317static bool move_normal_pmd (struct pagetable_move_control * pmc ,
299318 pmd_t * old_pmd , pmd_t * new_pmd )
@@ -306,6 +325,8 @@ static bool move_normal_pmd(struct pagetable_move_control *pmc,
306325
307326 if (!arch_supports_page_table_move ())
308327 return false;
328+ if (!uffd_supports_page_table_move (pmc ))
329+ return false;
309330 /*
310331 * The destination pmd shouldn't be established, free_pgtables()
311332 * should have released it.
@@ -332,15 +353,6 @@ static bool move_normal_pmd(struct pagetable_move_control *pmc,
332353 if (WARN_ON_ONCE (!pmd_none (* new_pmd )))
333354 return false;
334355
335- /* If this pmd belongs to a uffd vma with remap events disabled, we need
336- * to ensure that the uffd-wp state is cleared from all pgtables. This
337- * means recursing into lower page tables in move_page_tables(), and we
338- * can reuse the existing code if we simply treat the entry as "not
339- * moved".
340- */
341- if (vma_has_uffd_without_event_remap (vma ))
342- return false;
343-
344356 /*
345357 * We don't have to worry about the ordering of src and dst
346358 * ptlocks because exclusive mmap_lock prevents deadlock.
@@ -389,22 +401,15 @@ static bool move_normal_pud(struct pagetable_move_control *pmc,
389401
390402 if (!arch_supports_page_table_move ())
391403 return false;
404+ if (!uffd_supports_page_table_move (pmc ))
405+ return false;
392406 /*
393407 * The destination pud shouldn't be established, free_pgtables()
394408 * should have released it.
395409 */
396410 if (WARN_ON_ONCE (!pud_none (* new_pud )))
397411 return false;
398412
399- /* If this pud belongs to a uffd vma with remap events disabled, we need
400- * to ensure that the uffd-wp state is cleared from all pgtables. This
401- * means recursing into lower page tables in move_page_tables(), and we
402- * can reuse the existing code if we simply treat the entry as "not
403- * moved".
404- */
405- if (vma_has_uffd_without_event_remap (vma ))
406- return false;
407-
408413 /*
409414 * We don't have to worry about the ordering of src and dst
410415 * ptlocks because exclusive mmap_lock prevents deadlock.
0 commit comments