Re: [BUG] shmem: FALLOC_FL_PUNCH_HOLE vs fault-around race corrupts page cache / rss counters

From: Andrew Morton

Date: Thu Oct 08 2026 - 11:35:33 EST


On Thu, 8 Oct 2026 08:23:04 -0700 Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> wrote:

> A useful next step would be to instrument truncate_cleanup_folio(), e.g. warn
> immediately after unmap_mapping_folio() if folio_mapped() is still true.
> That should distinguish "unmap failed to remove an existing mapping" from
> "some path installed a new mapping afterwards", and narrow this down
> considerably.

does this seem useful? If so I can add it to mm-new/linux-next for a
while.


From: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
Subject: mm/truncate: catch shmem folios still mapped after unmap
Date: Thu Oct 8 08:29:04 AM PDT 2026

Instrument truncate_cleanup_folio() to determine where the shmem "still
mapped when deleted" state is introduced.

truncate_inode_folio() calls truncate_cleanup_folio() under the folio
lock, and truncate_cleanup_folio() calls unmap_mapping_folio() before
filemap_remove_folio(). If a shmem folio is still mapped immediately
after that unmap, then the unmap itself failed to remove all mappings (or
a path outside the folio-lock serialization installed one concurrently).

If this warning does not fire but the later "still mapped when deleted"
warning still does, the mapping must have appeared after this point. That
distinguishes the two cases without otherwise changing truncate behavior.

Limit the diagnostic to shmem and dump the folio on the first occurrence.

Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
---

mm/truncate.c | 10 ++++++++++
1 file changed, 10 insertions(+)

--- a/mm/truncate.c~shmem-truncate-unmap-debug
+++ a/mm/truncate.c
@@ -156,6 +156,16 @@ static void truncate_cleanup_folio(struc
if (folio_mapped(folio))
unmap_mapping_folio(folio);

+ /*
+ * Pin down where the shmem "still mapped when deleted" state appears:
+ * if the folio is clear here but mapped at removal, something installed
+ * a mapping after cleanup rather than surviving unmap_mapping_folio().
+ */
+ if (shmem_mapping(folio->mapping) &&
+ WARN_ON_ONCE(folio_mapped(folio)))
+ dump_page(&folio->page,
+ "shmem folio still mapped after unmap_mapping_folio");
+
if (folio_needs_release(folio))
folio_invalidate(folio, 0, folio_size(folio));

_