Re: [PATCH 11/16] mm/shmem: rescan after nonuniform folio splitting

From: Zi Yan

Date: Mon Oct 26 2026 - 22:32:56 EST


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

--
Best Regards,
Yan, Zi