As a first step to facilitate efficient post-eof zeroing in tmpfs, zero post-eof uptodate folios at swap out time. This ensures that post-eof ranges are zeroed "on disk" (i.e. analogous to traditional pagecache writeback) and facilitates zeroing on file size changes by allowing it to not have to swap in. Note that shmem_writeout() already zeroes !uptodate folios so this introduces some duplicate logic. We'll clean this up in the next patch. Signed-off-by: Brian Foster --- mm/shmem.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index 0a25ee095b86..5fb3c911894f 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1577,6 +1577,8 @@ int shmem_writeout(struct folio *folio, struct swap_iocb **plug, struct inode *inode = mapping->host; struct shmem_inode_info *info = SHMEM_I(inode); struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); + loff_t i_size = i_size_read(inode); + pgoff_t end_index = DIV_ROUND_UP(i_size, PAGE_SIZE); pgoff_t index; int nr_pages; bool split = false; @@ -1596,8 +1598,7 @@ int shmem_writeout(struct folio *folio, struct swap_iocb **plug, * (unless fallocate has been used to preallocate beyond EOF). */ if (folio_test_large(folio)) { - index = shmem_fallocend(inode, - DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE)); + index = shmem_fallocend(inode, end_index); if ((index > folio->index && index < folio_next_index(folio)) || !IS_ENABLED(CONFIG_THP_SWAP)) split = true; @@ -1647,6 +1648,20 @@ int shmem_writeout(struct folio *folio, struct swap_iocb **plug, folio_mark_uptodate(folio); } + /* + * Ranges beyond EOF must be zeroed at writeout time. This mirrors + * traditional writeback behavior and facilitates zeroing on file size + * changes without having to swap back in. + */ + if (folio_next_index(folio) >= end_index) { + size_t from = offset_in_folio(folio, i_size); + + if (index >= end_index) { + folio_zero_segment(folio, 0, folio_size(folio)); + } else if (from) + folio_zero_segment(folio, from, folio_size(folio)); + } + if (!folio_alloc_swap(folio)) { bool first_swapped = shmem_recalc_inode(inode, 0, nr_pages); int error; -- 2.51.1