Re: [PATCH 11/16] mm/shmem: rescan after nonuniform folio splitting
From: Baolin Wang
Date: Tue Oct 27 2026 - 04:01:17 EST
On 10/27/26 10:32 AM, Zi Yan wrote:
On Mon Oct 26, 2026 at 5:40 AM EDT, David Hildenbrand (Arm) wrote:
The final scan in shmem_undo_range() restarts after a successful split
only if the original folio is no longer large. A nonuniform split can
leave that folio large, so the scan skips the newly created folios.
Hole punching then leaves pages within the hole allocated even though
they could be discarded.
For example, a fault below the hole can allocate a 2 MiB folio after
boundary handling. Punching a 1 MiB hole at offset 64 KiB splits the
folio successfully but leaves the original folio at order 4. The scan
continues past all 512 pages, leaving 2 MiB allocated instead of 1 MiB.
The hole reads as zero, but the pages and their block charges remain.
Restart when the original folio is still in the mapping after partial
truncation, identified by checking folio->mapping. If the helper
removed the whole folio, no rescan is needed.
This paragraph is no longer needed after Zhang Yi's truncate fix, since
truncate_inode_partial_folio() returns true only if the folio is split.
The function returns false when the whole folio is truncated[1].
[1] https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git/tree/mm/truncate.c?h=mm-stable#n282
Fixes: 7460b470a131f ("mm/truncate: use folio_split() in truncate operation")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
---
mm/shmem.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
folio->mapping check is dropped and the comment is adjusted after the
patch is rebased on top of mm-stable because of the aforementioned
reason:
diff --git a/mm/shmem.c b/mm/shmem.c
index 7cf5a4d9d1ace..ddea31f44fb32 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1477,18 +1477,12 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, uoff_t lend,
} else if (truncate_inode_partial_folio(folio,
lstart, lend, NULL, NULL)) {
/*
- * If we split a page, reset the loop so
- * that we pick up the new sub pages.
- * Otherwise the THP was entirely
- * dropped or the target range was
- * zeroed, so just continue the loop as
- * is.
+ * The folio was split. Retry the scan
+ * to find the split folios.
*/
- if (!folio_test_large(folio)) {
- folio_unlock(folio);
- index = start;
- break;
- }
+ folio_unlock(folio);
+ index = start;
+ break;
} else {
/*
* Splitting failed, but the part in the
Thanks for explanation. LGTM.
Reviewed-by: Baolin Wang <baolin.wang@xxxxxxxxxxxxxxxxx>