[PATCH 7.2 v2 02/12] mm/khugepaged: add folio dirty check after try_to_unmap_flush()

Zi Yan
2026-04-13T19:21:00Z

This check ensures the correctness of collapse read-only THPs for FSes
after READ_ONLY_THP_FOR_FS is enabled by default for all FSes supporting
PMD THP pagecache.

READ_ONLY_THP_FOR_FS only supports read-only fd and uses mapping->nr_thps
and inode->i_writecount to prevent any write to read-only to-be-collapsed
folios. In upcoming commits, READ_ONLY_THP_FOR_FS will be removed and the
aforementioned mechanism will go away too. To ensure khugepaged functions
as expected after the changes, rollback if any folio is dirty after
try_to_unmap_flush() to , since a dirty folio means this read-only folio
got some writes via mmap can happen between try_to_unmap() and
try_to_unmap_flush() via cached TLB entries and khugepaged does not support
collapse writable pagecache folios.

Signed-off-by: Zi Yan <ziy@nvidia.com>
---
mm/khugepaged.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index d2f0acd2dac2..ec609e53082e 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -2121,6 +2121,24 @@ static enum scan_result collapse_file(struct mm_struct *mm, unsigned long addr,
*/
try_to_unmap_flush();

+ /*
+ * At this point, all folios are locked, unmapped, and all cached
+ * mappings in TLBs are flushed. No one else is able to write to these
+ * folios, since
+ * 1. writes via FS ops require folio locks (see write_begin_get_folio());
+ * 2. writes via mmap require taking a fault and locking folio locks.
+ *
+ * khugepaged only works for read-only fd, make sure all folios are
+ * clean, since writes via mmap can happen between try_to_unmap() and
+ * try_to_unmap_flush() via cached TLB entries.
+ */
+ list_for_each_entry(folio, &pagelist, lru) {
+ if (!is_shmem && (folio_test_dirty(folio))) {
+ result = SCAN_PAGE_DIRTY_OR_WRITEBACK;
+ goto rollback;
+ }
+ }
+
if (result == SCAN_SUCCEED && nr_none &&
!shmem_charge(mapping->host, nr_none))
result = SCAN_FAIL;
--
2.43.0