[PATCH 6.18 354/396] fs/proc/task_mmu: fix PAGEMAP_SCAN written state for unpopulated ptes
Greg Kroah-Hartman <[email protected]>
| Newsgroups | org.kernel.vger.stable,dev.linux.lists.patches |
|---|---|
| Message-ID | <[email protected]> |
6.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Kiryl Shutsemau (Meta) <[email protected]> [ Upstream commit 07b4377bdbe74a3ec0c8da5849d014f70e003384 ] PAGEMAP_SCAN reports an unpopulated pte differently depending on which path serves the request. The PAGE_IS_WRITTEN fast path in pagemap_scan_pmd_entry() reports a pte_none as written (and, under PM_SCAN_WP_MATCHING, arms a marker); pagemap_page_category() returns 0 for the same pte_none. A request that cannot take the fast path (an extra category bit, category_anyof_mask or category_inverted) therefore reports the pte as clean and skips arming it. A range that was populated and then MADV_DONTNEED'd reads as written via one mask and clean via another, and in the latter case is not re-armed for the next round -- an incremental-dump consumer (e.g. CRIU) using a richer mask drops the zapped range and stops tracking writes to it. Report pte_none as written in pagemap_page_category() too. A pte_none carries no uffd-wp marker, i.e. it is not write-protected -- the same condition under which the present and swap cases already report PAGE_IS_WRITTEN. The fast path applies no VMA test, so neither does this. The hugetlb and fully-unpopulated-PMD (no page table) scans have no PAGE_IS_WRITTEN fast path, so they do not exhibit the per-entry divergence and are left unchanged. Add a pagemap_ioctl selftest that populates a range, drops it with MADV_DONTNEED, and checks that the fast path and the generic (category_anyof_mask) path both report every page written. Link: https://lore.kernel.org/[email protected] Fixes: 12f6b01a0bcb ("fs/proc/task_mmu: add fast paths to get/clear PAGE_IS_WRITTEN flag") Signed-off-by: Kiryl Shutsemau <[email protected]> Cc: Muhammad Usama Anjum <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Jann Horn <[email protected]> Cc: Liam R. Howlett <[email protected]> Cc: Lorenzo Stoakes <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Mike Rapoport <[email protected]> Cc: Pedro Falcato <[email protected]> Cc: Peter Xu <[email protected]> Cc: Shuah Khan <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Cc: Vlastimil Babka <[email protected]> Assisted-by: Claude:claude-fable-5 Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> (cherry picked from commit 07b4377bdbe74a3ec0c8da5849d014f70e003384) [ kas: fix only; selftest hunk dropped (pagemap_ioctl.c differs on this tree). Add the pte_none early-return before the pte_present branch ] Signed-off-by: Kiryl Shutsemau (Meta) <[email protected]> Signed-off-by: Sasha Levin <[email protected]> --- fs/proc/task_mmu.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 0cec16f9e9afd..48455e2a66a1e 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -2326,6 +2326,19 @@ static unsigned long pagemap_page_category(struct pagemap_scan_private *p, { unsigned long categories = 0; + if (pte_none(pte)) { + /* + * An unpopulated pte carries no uffd-wp marker, i.e. it is not + * write-protected, the same condition under which the present + * and swap cases below report PAGE_IS_WRITTEN. Report it here + * too so this generic path agrees with the PAGE_IS_WRITTEN fast + * path in pagemap_scan_pmd_entry(), which reports pte_none as + * written and, under PM_SCAN_WP_MATCHING, arms a marker. The + * fast path applies no VMA test, so neither does this. + */ + return PAGE_IS_WRITTEN; + } + if (pte_present(pte)) { struct page *page; -- 2.53.0