From 8fb1ad47dcedfc40ce13dd1a74d6497cf5fff878 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Thu, 18 Jun 2026 17:28:42 +0800 Subject: [PATCH] mm: mincore: use walk_page_range_vma() in do_mincore() Patch series "mm: convert to walk_page_range_vma() to eliminate find_vma()", v2. walk_page_range() performs a find_vma() lookup on each page table walk. For callers that already hold a valid VMA and operate on a known single-VMA range, this lookup is redundant. Replace walk_page_range() with walk_page_range_vma() where the caller guarantees single-VMA semantics. This patch (of 4): do_mincore() uses walk_page_range() to walk the page table. Fortunately, the caller always passes start/end that falls within a single VMA, so it's safe to use the walk_page_range_vma() in do_mincore() to eliminate an unnecessary find_vma() lookup. Unlike walk_page_range(), walk_page_range_vma() does not call walk_page_test(), which handles VM_PFNMAP by invoking ->pte_hole() to skip the page table walk. Without this check, PFNMAP PTEs would be treated as present by mincore_pte_range(), changing the returned residency status. Handle VM_PFNMAP explicitly in do_mincore() to preserve the original behavior. [akpm@linux-foundation.org: simplify comment, per Pedro] Link: https://lore.kernel.org/ajP9bQhmvR9OX0VE@pedro-suse Link: https://lore.kernel.org/20260618092845.3905740-1-wangkefeng.wang@huawei.com Link: https://lore.kernel.org/20260618092845.3905740-2-wangkefeng.wang@huawei.com Signed-off-by: Kefeng Wang Acked-by: Zi Yan Acked-by: David Hildenbrand (Arm) Reviewed-by: Pedro Falcato Cc: Alistair Popple Cc: Byungchul Park Cc: Gregory Price Cc: Joshua Hahn Cc: Liam R. Howlett Cc: Lorenzo Stoakes Cc: Matthew Brost Cc: Rakie Kim Cc: Suren Baghdasaryan Cc: Vlastimil Babka Cc: Ying Huang Signed-off-by: Andrew Morton --- mm/mincore.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mm/mincore.c b/mm/mincore.c index c8757c5085bf..53b982803771 100644 --- a/mm/mincore.c +++ b/mm/mincore.c @@ -258,7 +258,16 @@ static long do_mincore(unsigned long addr, unsigned long pages, unsigned char *v memset(vec, 1, pages); return pages; } - err = walk_page_range(vma->vm_mm, addr, end, &mincore_walk_ops, vec); + + /* + * mincore historically reports PFNMAP mappings as non-resident. + */ + if (vma->vm_flags & VM_PFNMAP) { + __mincore_unmapped_range(addr, end, vma, vec); + return (end - addr) >> PAGE_SHIFT; + } + + err = walk_page_range_vma(vma, addr, end, &mincore_walk_ops, vec); if (err < 0) return err; return (end - addr) >> PAGE_SHIFT;