FAILED: patch "[PATCH] userfaultfd: wait on source PMD during UFFDIO_MOVE" failed to apply to 6.18-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 4165b7d1c45c2da0dfefe528f8d1fb7d79f0d344
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026080544-exit-cesarean-7929@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 4165b7d1c45c2da0dfefe528f8d1fb7d79f0d344 Mon Sep 17 00:00:00 2001
From: Usama Arif <[email protected]>
Date: Sun, 5 Jul 2026 06:12:31 -0700
Subject: [PATCH] userfaultfd: wait on source PMD during UFFDIO_MOVE
move_pages_huge_pmd() snapshots src_pmdval under src_ptl, drops the lock, and, for migration entries, waits with pmd_migration_entry_wait().
Passing &src_pmdval is wrong. pmd_migration_entry_wait() must lock and re-read the real page-table PMD; on split-PMD-lock kernels, a stack address also resolves to the wrong lock. softleaf_entry_wait_on_locked() then waits without a folio reference, which is safe only while serialized against migration-entry removal by the real PT lock.
Pass src_pmd, matching __handle_mm_fault() and hmm_vma_walk_pmd().
mm/huge_memory.c +1 -1
@@ -2774,7 +2774,7 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pmif (!pmd_trans_huge (src_pmdval)) {spin_unlock (src_ptl);if (pmd_is_migration_entry (src_pmdval)) { -pmd_migration_entry_wait (mm, &src_pmdval); +pmd_migration_entry_wait (mm, src_pmd);return -EAGAIN ; }return -ENOENT ;
Sasha Levin
maintainerPATCH 1/3 fs/proc/task_mmu: refactor pagemap_pmd_range()
From: Lorenzo Stoakes <[email protected]>
[ Upstream commit de4d6c94914f3659f0b51725e23e637d4e9f78cc ]
Separate out THP logic so we can drop an indentation level and reduce the amount of noise in this function.
We add pagemap_pmd_range_thp() for this purpose.
While we're here, convert the VM_BUG_ON() to a VM_WARN_ON_ONCE() at the same time.
No functional change intended.
Stable-dep-of: 4165b7d1c45c ("userfaultfd: wait on source PMD during UFFDIO_MOVE")
--- fs/proc/task_mmu.c | 146 ++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 69 deletions(-)
fs/proc/task_mmu.c +77 -69
@@ -1989,90 +1989,98 @@ static pagemap_entry_t pte_to_pagemap_entry(struct pagemapread *pm,return make_pme (frame, flags); } -static int pagemap_pmd_range (pmd_t *pmdp,unsigned long addr,unsigned long end, -struct mm_walk *walk) +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +static int pagemap_pmd_range_thp (pmd_t *pmdp,unsigned long addr, +unsigned long end,struct vm_area_struct *vma, +struct pagemapread *pm) { -struct vm_area_struct *vma = walk->vma; -struct pagemapread *pm = walk->private; -spinlock_t *ptl; -pte_t *pte, *orig_pte; +unsigned int idx = (addr & ~PMD_MASK ) >>PAGE_SHIFT ; +u64 flags =0 , frame =0 ; +pmd_t pmd = *pmdp; +struct page *page =NULL ; +struct folio *folio =NULL ;int err =0 ; -#ifdef CONFIG_TRANSPARENT_HUGEPAGE - ptl =pmd_trans_huge_lock (pmdp, vma); -if (ptl) { -unsigned int idx = (addr & ~PMD_MASK ) >>PAGE_SHIFT ; -u64 flags =0 , frame =0 ; -pmd_t pmd = *pmdp; -struct page *page =NULL ; -struct folio *folio =NULL ; +if (vma->vm_flags &VM_SOFTDIRTY ) + flags |=PM_SOFT_DIRTY ; -if (vma->vm_flags &VM_SOFTDIRTY ) - flags |=PM_SOFT_DIRTY ; +if (pmd_present (pmd)) { + page =pmd_page (pmd); -if (pmd_present (pmd)) { - page =pmd_page (pmd); + flags |=PM_PRESENT ; +if (pmd_soft_dirty (pmd)) + flags |=PM_SOFT_DIRTY ; +if (pmd_uffd_wp (pmd)) + flags |=PM_UFFD_WP ; +if (pm->show_pfn) + frame =pmd_pfn (pmd) + idx; + }else if (thp_migration_supported () &&is_swap_pmd (pmd)) { +swp_entry_t entry =pmd_to_swp_entry (pmd); +unsigned long offset; - flags |=PM_PRESENT ; -if (pmd_soft_dirty (pmd)) - flags |=PM_SOFT_DIRTY ; -if (pmd_uffd_wp (pmd)) - flags |=PM_UFFD_WP ; -if (pm->show_pfn) - frame =pmd_pfn (pmd) + idx; - } -#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION - else if (is_swap_pmd(pmd)) { -swp_entry_t entry =pmd_to_swp_entry (pmd); -unsigned long offset; - -if (pm->show_pfn) { -if (is_pfn_swap_entry (entry)) - offset =swp_offset_pfn (entry) + idx; -else - offset =swp_offset (entry) + idx; - frame =swp_type (entry) | - (offset <<MAX_SWAPFILES_SHIFT ); - } - flags |=PM_SWAP ; -if (pmd_swp_soft_dirty (pmd)) - flags |=PM_SOFT_DIRTY ; -if (pmd_swp_uffd_wp (pmd)) - flags |=PM_UFFD_WP ; -VM_BUG_ON (!is_pmd_migration_entry (pmd)); - page =pfn_swap_entry_to_page (entry); +if (pm->show_pfn) { +if (is_pfn_swap_entry (entry)) + offset =swp_offset_pfn (entry) + idx; +else + offset =swp_offset (entry) + idx; + frame =swp_type (entry) | + (offset <<MAX_SWAPFILES_SHIFT ); } -#endif + flags |=PM_SWAP ; +if (pmd_swp_soft_dirty (pmd)) + flags |=PM_SOFT_DIRTY ; +if (pmd_swp_uffd_wp (pmd)) + flags |=PM_UFFD_WP ; +VM_WARN_ON_ONCE (!is_pmd_migration_entry (pmd)); + page =pfn_swap_entry_to_page (entry); + } -if (page) { - folio =page_folio (page); -if (!folio_test_anon (folio)) - flags |=PM_FILE ; - } +if (page) { + folio =page_folio (page); +if (!folio_test_anon (folio)) + flags |=PM_FILE ; + } -for (; addr != end; addr +=PAGE_SIZE , idx++) { -u64 cur_flags = flags; -pagemap_entry_t pme; +for (; addr != end; addr +=PAGE_SIZE , idx++) { +u64 cur_flags = flags; +pagemap_entry_t pme; -if (folio && (flags &PM_PRESENT ) && -__folio_page_mapped_exclusively (folio, page)) - cur_flags |=PM_MMAP_EXCLUSIVE ; +if (folio && (flags &PM_PRESENT ) && +__folio_page_mapped_exclusively (folio, page)) + cur_flags |=PM_MMAP_EXCLUSIVE ; - pme =make_pme (frame, cur_flags); - err =add_to_pagemap (&pme, pm); -if (err) -break ; -if (pm->show_pfn) { -if (flags &PM_PRESENT ) - frame++; -else if (flags &PM_SWAP ) - frame += (1 <<MAX_SWAPFILES_SHIFT ); - } + pme =make_pme (frame, cur_flags); + err =add_to_pagemap (&pme, pm); +if (err) +break ; +if (pm->show_pfn) { +if (flags &PM_PRESENT ) + frame++; +else if (flags &PM_SWAP ) + frame += (1 <<MAX_SWAPFILES_SHIFT ); } + } +return err; +} +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + +static int pagemap_pmd_range (pmd_t *pmdp,unsigned long addr,unsigned long end, +struct mm_walk *walk) +{ +struct vm_area_struct *vma = walk->vma; +struct pagemapread *pm = walk->private; +spinlock_t *ptl; +pte_t *pte, *orig_pte; +int err =0 ; + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + ptl =pmd_trans_huge_lock (pmdp, vma); +if (ptl) { + err =pagemap_pmd_range_thp (pmdp, addr, end, vma, pm);spin_unlock (ptl);return err; } -#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +#endif /* * We can assume that @vma always points to a valid one and @end never
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 mm: replace pmd_to_swp_entry() with softleaf_from_pmd()
From: Lorenzo Stoakes <[email protected]>
[ Upstream commit 0ac881efe16468503e8c1e7d8a7210b75f027ce3 ]
Introduce softleaf_from_pmd() to do the equivalent operation for PMDs that softleaf_from_pte() fulfils, and cascade changes through code base accordingly, introducing helpers as necessary.
We are then able to eliminate pmd_to_swp_entry(), is_pmd_migration_entry(), is_pmd_device_private_entry() and is_pmd_non_present_folio_entry().
This further establishes the use of leaf operations throughout the code base and further establishes the foundations for eliminating is_swap_pmd().
No functional change intended.
Stable-dep-of: 4165b7d1c45c ("userfaultfd: wait on source PMD during UFFDIO_MOVE")
--- fs/proc/task_mmu.c | 2 +- include/linux/swapops.h | 4 ++-- mm/hmm.c | 2 +- mm/huge_memory.c | 20 ++++++++++---------- mm/khugepaged.c | 2 +- mm/madvise.c | 2 +- mm/memory.c | 4 ++-- mm/mempolicy.c | 2 +- mm/migrate.c | 2 +- mm/page_vma_mapped.c | 2 +- mm/pagewalk.c | 2 +- mm/pgtable-generic.c | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-)
fs/proc/task_mmu.c +1 -1
@@ -2031,7 +2031,7 @@ static int pagemap_pmd_range_thp(pmd_t *pmdp, unsigned long addr, flags |=PM_SOFT_DIRTY ;if (pmd_swp_uffd_wp (pmd)) flags |=PM_UFFD_WP ; -VM_WARN_ON_ONCE (!is_pmd_migration_entry (pmd)); +VM_WARN_ON_ONCE (!pmd_is_migration_entry (pmd)); page =pfn_swap_entry_to_page (entry); }
include/linux/swapops.h +2 -2
@@ -570,7 +570,7 @@ static inline pmd_t swp_entry_to_pmd(swp_entry_t entry)return __swp_entry_to_pmd (arch_entry); } -static inline int is_pmd_migration_entry (pmd_t pmd) +static inline int pmd_is_migration_entry (pmd_t pmd) {return is_swap_pmd (pmd) &&is_migration_entry (pmd_to_swp_entry (pmd)); }
@@ -599,7 +599,7 @@ static inline pmd_t swp_entry_to_pmd(swp_entry_t entry)return __pmd (0 ); } -static inline int is_pmd_migration_entry (pmd_t pmd) +static inline int pmd_is_migration_entry (pmd_t pmd) {return 0 ; }
mm/hmm.c +1 -1
@@ -407,7 +407,7 @@ static int hmm_vma_walk_pmd(pmd_t *pmdp,if (pmd_none (pmd))return hmm_vma_walk_hole (start, end,-1 , walk); -if (thp_migration_supported () &&is_pmd_migration_entry (pmd)) { +if (thp_migration_supported () &&pmd_is_migration_entry (pmd)) {if (hmm_range_need_fault (hmm_vma_walk, hmm_pfns, npages,0 )) { hmm_vma_walk->last = addr;pmd_migration_entry_wait (walk->mm, pmdp);
mm/huge_memory.c +10 -10
@@ -1707,7 +1707,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,if (unlikely (is_swap_pmd (pmd))) {swp_entry_t entry =pmd_to_swp_entry (pmd); -VM_BUG_ON (!is_pmd_migration_entry (pmd)); +VM_BUG_ON (!pmd_is_migration_entry (pmd));if (!is_readable_migration_entry (entry)) { entry =make_readable_migration_entry (swp_offset (entry));
@@ -2117,7 +2117,7 @@ bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,if (unlikely (!pmd_present (orig_pmd))) {VM_BUG_ON (thp_migration_supported () && - !is_pmd_migration_entry (orig_pmd)); + !pmd_is_migration_entry (orig_pmd)); goto out; }
@@ -2218,7 +2218,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, }else if (thp_migration_supported ()) {swp_entry_t entry; -VM_BUG_ON (!is_pmd_migration_entry (orig_pmd)); +VM_BUG_ON (!pmd_is_migration_entry (orig_pmd)); entry =pmd_to_swp_entry (orig_pmd); folio =pfn_swap_entry_folio (entry); flush_needed =0 ;
@@ -2268,7 +2268,7 @@ static inline int pmd_move_must_withdraw(spinlock_t *new_pmd_ptl,static pmd_t move_soft_dirty_pmd (pmd_t pmd) {#ifdef CONFIG_MEM_SOFT_DIRTY -if (unlikely (is_pmd_migration_entry (pmd))) +if (unlikely (pmd_is_migration_entry (pmd))) pmd =pmd_swp_mksoft_dirty (pmd);else if (pmd_present (pmd)) pmd =pmd_mksoft_dirty (pmd);
@@ -2371,7 +2371,7 @@ int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,struct folio *folio =pfn_swap_entry_folio (entry);pmd_t newpmd; -VM_BUG_ON (!is_pmd_migration_entry (*pmd)); +VM_BUG_ON (!pmd_is_migration_entry (*pmd));if (is_writable_migration_entry (entry)) {/* * A protection check is difficult so
@@ -2559,7 +2559,7 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pmif (!pmd_trans_huge (src_pmdval)) {spin_unlock (src_ptl); -if (is_pmd_migration_entry (src_pmdval)) { +if (pmd_is_migration_entry (src_pmdval)) {pmd_migration_entry_wait (mm, &src_pmdval);return -EAGAIN ; }
@@ -2848,7 +2848,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,VM_BUG_ON (haddr & ~HPAGE_PMD_MASK );VM_BUG_ON_VMA (vma->vm_start > haddr, vma);VM_BUG_ON_VMA (vma->vm_end < haddr +HPAGE_PMD_SIZE , vma); -VM_BUG_ON (!is_pmd_migration_entry (*pmd) && !pmd_trans_huge (*pmd)); +VM_BUG_ON (!pmd_is_migration_entry (*pmd) && !pmd_trans_huge (*pmd));count_vm_event (THP_SPLIT_PMD );
@@ -2862,7 +2862,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,zap_deposited_table (mm, pmd);if (!vma_is_dax (vma) &&vma_is_special_huge (vma))return ; -if (unlikely (is_pmd_migration_entry (old_pmd))) { +if (unlikely (pmd_is_migration_entry (old_pmd))) {swp_entry_t entry; entry =pmd_to_swp_entry (old_pmd);
@@ -2898,7 +2898,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,return __split_huge_zero_page_pmd (vma, haddr, pmd); } - pmd_migration =is_pmd_migration_entry (*pmd); + pmd_migration =pmd_is_migration_entry (*pmd);if (unlikely (pmd_migration)) {swp_entry_t entry;
@@ -3058,7 +3058,7 @@ void split_huge_pmd_locked(struct vm_area_struct *vma, unsigned long address, pmd_t *pmd, bool freeze) {VM_WARN_ON_ONCE (!IS_ALIGNED (address,HPAGE_PMD_SIZE )); -if (pmd_trans_huge (*pmd) ||is_pmd_migration_entry (*pmd)) +if (pmd_trans_huge (*pmd) ||pmd_is_migration_entry (*pmd))__split_huge_pmd_locked (vma, pmd, address, freeze); }
mm/khugepaged.c +1 -1
@@ -939,7 +939,7 @@ static inline int check_pmd_state(pmd_t *pmd)* collapse it. Migration success or failure will eventually end * up with a present PMD mapping a folio again. */ -if (is_pmd_migration_entry (pmde)) +if (pmd_is_migration_entry (pmde))return SCAN_PMD_MAPPED ;if (!pmd_present (pmde))return SCAN_PMD_NULL ;
mm/madvise.c +1 -1
@@ -391,7 +391,7 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd,if (unlikely (!pmd_present (orig_pmd))) {VM_BUG_ON (thp_migration_supported () && - !is_pmd_migration_entry (orig_pmd)); + !pmd_is_migration_entry (orig_pmd)); goto huge_unlock; }
mm/memory.c +2 -2
@@ -6327,8 +6327,8 @@ static vm_fault_t __handle_mm_fault(struct vm_area_struct *vma,if (unlikely (is_swap_pmd (vmf.orig_pmd))) {VM_BUG_ON (thp_migration_supported () && - !is_pmd_migration_entry (vmf.orig_pmd)); -if (is_pmd_migration_entry (vmf.orig_pmd)) + !pmd_is_migration_entry (vmf.orig_pmd)); +if (pmd_is_migration_entry (vmf.orig_pmd))pmd_migration_entry_wait (mm, vmf.pmd);return 0 ; }
mm/mempolicy.c +1 -1
@@ -651,7 +651,7 @@ static void queue_folios_pmd(pmd_t *pmd, struct mm_walk *walk)struct folio *folio;struct queue_pages *qp = walk->private; -if (unlikely (is_pmd_migration_entry (*pmd))) { +if (unlikely (pmd_is_migration_entry (*pmd))) { qp->nr_failed++;return ; }
mm/migrate.c +1 -1
@@ -542,7 +542,7 @@ void pmd_migration_entry_wait(struct mm_struct *mm, pmd_t *pmd)spinlock_t *ptl; ptl =pmd_lock (mm, pmd); -if (!is_pmd_migration_entry (*pmd)) +if (!pmd_is_migration_entry (*pmd)) goto unlock;migration_entry_wait_on_locked (pmd_to_swp_entry (*pmd), ptl);return ;
mm/page_vma_mapped.c +1 -1
@@ -246,7 +246,7 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)*/ pmde =pmdp_get_lockless (pvmw->pmd); -if (pmd_trans_huge (pmde) ||is_pmd_migration_entry (pmde)) { +if (pmd_trans_huge (pmde) ||pmd_is_migration_entry (pmde)) { pvmw->ptl =pmd_lock (mm, pvmw->pmd); pmde = *pvmw->pmd;if (!pmd_present (pmde)) {
mm/pagewalk.c +1 -1
@@ -985,7 +985,7 @@ struct folio *folio_walk_start(struct folio_walk *fw, goto found; } }else if ((flags &FW_MIGRATION ) && -is_pmd_migration_entry (pmd)) { +pmd_is_migration_entry (pmd)) {swp_entry_t entry =pmd_to_swp_entry (pmd); page =pfn_swap_entry_to_page (entry);
mm/pgtable-generic.c +1 -1
@@ -291,7 +291,7 @@ pte_t *___pte_offset_map(pmd_t *pmd, unsigned long addr, pmd_t *pmdvalp)if (pmdvalp) *pmdvalp = pmdval; -if (unlikely (pmd_none (pmdval) ||is_pmd_migration_entry (pmdval))) +if (unlikely (pmd_none (pmdval) ||pmd_is_migration_entry (pmdval))) goto nomap;if (unlikely (pmd_trans_huge (pmdval))) goto nomap;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 userfaultfd: wait on source PMD during UFFDIO_MOVE
In reply to Sasha LevinFrom: Usama Arif <[email protected]>
[ Upstream commit 4165b7d1c45c2da0dfefe528f8d1fb7d79f0d344 ]
move_pages_huge_pmd() snapshots src_pmdval under src_ptl, drops the lock, and, for migration entries, waits with pmd_migration_entry_wait().
Passing &src_pmdval is wrong. pmd_migration_entry_wait() must lock and re-read the real page-table PMD; on split-PMD-lock kernels, a stack address also resolves to the wrong lock. softleaf_entry_wait_on_locked() then waits without a folio reference, which is safe only while serialized against migration-entry removal by the real PT lock.
Pass src_pmd, matching __handle_mm_fault() and hmm_vma_walk_pmd().
--- mm/huge_memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/huge_memory.c +1 -1
@@ -2560,7 +2560,7 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pmif (!pmd_trans_huge (src_pmdval)) {spin_unlock (src_ptl);if (pmd_is_migration_entry (src_pmdval)) { -pmd_migration_entry_wait (mm, &src_pmdval); +pmd_migration_entry_wait (mm, src_pmd);return -EAGAIN ; }return -ENOENT ;
Signature · 1 line
2.53.0