Re: [PATCH v3] mm/shmem: remove truncated folios from the page cache in batches

From: Baolin Wang

Date: Thu Nov 12 2026 - 04:55:51 EST




On 11/12/26 5:05 PM, Qiliang Yuan wrote:
truncate_inode_pages_range() takes the folios it finds out of the page
cache with delete_from_page_cache_batch(), which takes the inode's
i_lock and the i_pages lock once for each batch of up to
FOLIO_BATCH_SIZE folios.

shmem_undo_range() calls truncate_inode_folio() on each folio instead,
so filemap_remove_folio() takes and drops both locks once per folio.
Truncating, punching or freeing a tmpfs file or memfd made of small
folios, such as a large /dev/shm segment, pays for that on every page.

Clean each folio up as truncate_inode_folio() does and, once the swap
entries are gone, pass the batch to delete_from_page_cache_batch(),
which needs truncate_cleanup_folio() outside mm/truncate.c. Undoing a
failed fallocate() only removes the folios that are not uptodate, so
keep removing those one at a time.

Dropping an 8 GiB file of 4K folios in a 32 vCPU VM takes (median of
five runs, averaged over two boots of each kernel):

operation before (ms) after (ms) change
ftruncate() to 0 1144 901 -21%
hole punch 1148 906 -21%
close() of a memfd 1139 912 -20%
unlink() 1142 914 -20%

Files of PMD-sized folios take 18-31 ms with or without this change.

Signed-off-by: Qiliang Yuan <qiliang.yuan@xxxxxxxxx>
---

LGTM.
Reviewed-by: Baolin Wang <baolin.wang@xxxxxxxxxxxxxxxxx>