Re: [PATCH v3 17/47] mm/khugepaged: preserve dirty bits when collapsing PTE-mapped THPs

From: Lance Yang

Date: Mon Nov 02 2026 - 01:08:36 EST



On Sat, Oct 31, 2026 at 10:39:46AM +0100, David Hildenbrand (Arm) wrote:
>From: Chris Mason <mason@xxxxxxxxxx>
>
>try_collapse_pte_mapped_thp() clears PTEs without transferring their dirty
>bits to the folio. A shmem read fault can map a clean folio writable, so
>a later store only dirties the PTE. Losing that dirty bit allows reclaim
>to discard modified data.
>
>The assumption that regular files are read-only is also obsolete since
>commit 1b6444331bebb ("mm/khugepaged: enable clean pagecache folio collapse
>for writable files"). In any case, transferring PTE dirty bits to the folio
>when removing mappings (and while the folio is still mapped) is the right
>thing to do.
>
>Use get_and_clear_ptes() to collect the dirty bits and mark the folio
>dirty before unmapping it. Update the comment.
>
>This was reproduced with shmem using MADV_COLLAPSE followed by
>MADV_PAGEOUT.
>
>Fix generated by an LLM and sent by Chris Mason in private.
>
>Fixes: 27e1f8273113 ("khugepaged: enable collapse pmd for pte-mapped THP")
>Fixes: 1b6444331bebb ("mm/khugepaged: enable clean pagecache folio collapse for writable files")
>Cc: stable@xxxxxxxxxxxxxxx
>Signed-off-by: Chris Mason <mason@xxxxxxxxxx>
>[ david: adjust comment; simplify description; cover file-thp as well ]
>Reviewed-by: Pedro Falcato <pfalcato@xxxxxxx>
>Reviewed-by: Gregory Price (Meta) <gourry@xxxxxxxxxx>
>Tested-by: Gregory Price (Meta) <gourry@xxxxxxxxxx>
>Tested-by: Muhammad Usama Anjum <usama.anjum@xxxxxxx>
>Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
>---
> mm/khugepaged.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
>diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>index 34ebb37c862c0..ce794d9760a87 100644
>--- a/mm/khugepaged.c
>+++ b/mm/khugepaged.c
>@@ -1995,9 +1995,10 @@ static enum scan_result try_collapse_pte_mapped_thp(struct mm_struct *mm, unsign
> /*
> * Must clear entry, or a racing truncate may re-remove it.
> * TLB flush can be left until pmdp_collapse_flush() does it.
>- * PTE dirty? Shmem page is already dirty; file is read-only.
> */
>- clear_ptes(mm, addr, pte, nr_batch_ptes);
>+ ptent = get_and_clear_ptes(mm, addr, pte, nr_batch_ptes);

I went through get_and_clear_ptes() as well. It merges dirty bits across
the batch, so we're covered even when the first PTE is clean and a later
one is dirty.

LGTM!

Reviewed-by: Lance Yang <lance.yang@xxxxxxxxx>

>+ if (pte_dirty(ptent))
>+ folio_mark_dirty(folio);
> folio_remove_rmap_ptes(folio, page, nr_batch_ptes, vma);
> nr_mapped_ptes += nr_batch_ptes;
> }
>
>--
>2.43.0
>
>