queue_folios_pte_range() already pairs vm_normal_folio() with an explicit folio_is_zone_device() check before adding folios to the migration pagelist. vm_normal_folio() alone does not reject zone device memory (a present device-coherent page in a normal VMA is returned as "normal"). Mirror the explicit check in the two other walkers. queue_folios_pmd() uses pmd_folio() directly and can encounter a present zone device PMD - e.g. a device-coherent THP. This is not filtered by existing checks: !pmd_present() - only rejects non-present device-private and migration entries vma_migratable() - excludes DAX and VM_PFNMAP. The early return also means such a folio is no longer counted in qp->nr_failed under MPOL_MF_STRICT. This is the same pattern used by queue_folios_pte_range() (skipping zone device without failing). queue_folios_hugetlb() cannot see zone device memory - hugetlb folios are never ZONE_DEVICE - so the check there is purely defensive and keeps all three walkers consistent. Signed-off-by: Gregory Price (Meta) --- mm/mempolicy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 5720f7f54d94..bd79e61a40d1 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -668,6 +668,8 @@ static void queue_folios_pmd(pmd_t *pmd, struct mm_walk *walk) } if (!queue_folio_required(folio, qp)) return; + if (folio_is_zone_device(folio)) + return; if (!(qp->flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) || !vma_migratable(walk->vma) || !migrate_folio_add(folio, qp->pagelist, qp->flags)) @@ -797,6 +799,8 @@ static int queue_folios_hugetlb(pte_t *pte, unsigned long hmask, folio = pfn_folio(pte_pfn(ptep)); if (!queue_folio_required(folio, qp)) goto unlock; + if (folio_is_zone_device(folio)) + goto unlock; if (!(flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) || !vma_migratable(walk->vma)) { qp->nr_failed++; -- 2.55.0