Re: [RFC v2 12/21] mm: thp: handle split failure in device migration
From: Usama Arif <usama.arif@linux.dev>
Date: 2026-03-04 11:56:06
Also in:
linux-mm, linux-s390, lkml
On 02/03/2026 21:20, Nico Pache wrote:
On Thu, Feb 26, 2026 at 4:34 AM Usama Arif [off-list ref] wrote:quoted
Device memory migration has two call sites that split huge PMDs: migrate_vma_split_unmapped_folio(): Called from migrate_vma_pages() when migrating a PMD-mapped THP to a destination that doesn't support compound pages. It splits the PMD then splits the folio via folio_split_unmapped(). If the PMD split fails, folio_split_unmapped() would operate on an unsplit folio with inconsistent page table state. Propagate -ENOMEM to skip this page's migration. This is safe as folio_split_unmapped failure would be propagated in a similar way. migrate_vma_insert_page(): Called from migrate_vma_pages() when inserting a page into a VMA during migration back from device memory. If a huge zero PMD exists at the target address, it must be split before PTE insertion. If the split fails, the subsequent pte_alloc() and set_pte_at() would operate on a PMD slot still occupied by the huge zero entry. Use goto abort, consistent with other allocation failures in this function. Signed-off-by: Usama Arif <usama.arif@linux.dev> --- mm/migrate_device.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)diff --git a/mm/migrate_device.c b/mm/migrate_device.c index 78c7acf024615..bc53e06fd9735 100644 --- a/mm/migrate_device.c +++ b/mm/migrate_device.c@@ -909,7 +909,13 @@ static int migrate_vma_split_unmapped_folio(struct migrate_vma *migrate, int ret = 0; folio_get(folio);Should we be concerned about this folio_get? Are we incrementing a reference that was already held if we back out of the split?
Good catch! I think this bug existed even before this patch, if folio_split_unmapped fails, the reference is still there. Let me send an independent fix for this.
-- Nicoquoted
- split_huge_pmd_address(migrate->vma, addr, true); + /* + * If PMD split fails, folio_split_unmapped would operate on an + * unsplit folio with inconsistent page table state. + */ + ret = split_huge_pmd_address(migrate->vma, addr, true); + if (ret) + return ret; ret = folio_split_unmapped(folio, 0); if (ret) return ret;