[PATCH 4/4] mm/mempolicy: skip zone device folios when queueing folios

Gregory Price <[email protected]> Tue, 28 Jul 2026 15:47:14 -0400
Newsgroups dev.linux.lists.damon,org.kernel.vger.linux-kernel,org.kvack.linux-mm
Message-ID <[email protected]>
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) <[email protected]>
---
 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