Skip to content

Commit 44bcabd

Browse files
Hugh Dickinsakpm00
Hugh Dickins
authored andcommitted
tmpfs: fix data loss from failed fallocate
Fix tmpfs data loss when the fallocate system call is interrupted by a signal, or fails for some other reason. The partial folio handling in shmem_undo_range() forgot to consider this unfalloc case, and was liable to erase or truncate out data which had already been committed earlier. It turns out that none of the partial folio handling there is appropriate for the unfalloc case, which just wants to proceed to removal of whole folios: which find_get_entries() provides, even when partially covered. Original patch by Rui Wang. Link: https://lore.kernel.org/linux-mm/[email protected]/ Link: https://lkml.kernel.org/r/[email protected] Fixes: b9a8a41 ("truncate,shmem: Handle truncates that split large folios") Signed-off-by: Hugh Dickins <[email protected]> Reported-by: Guoqi Chen <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Cc: Rui Wang <[email protected]> Cc: Huacai Chen <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Vishal Moola (Oracle) <[email protected]> Cc: <[email protected]> [5.17+] Signed-off-by: Andrew Morton <[email protected]>
1 parent de16d6e commit 44bcabd

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

mm/shmem.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,15 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
948948
index++;
949949
}
950950

951+
/*
952+
* When undoing a failed fallocate, we want none of the partial folio
953+
* zeroing and splitting below, but shall want to truncate the whole
954+
* folio when !uptodate indicates that it was added by this fallocate,
955+
* even when [lstart, lend] covers only a part of the folio.
956+
*/
957+
if (unfalloc)
958+
goto whole_folios;
959+
951960
same_folio = (lstart >> PAGE_SHIFT) == (lend >> PAGE_SHIFT);
952961
folio = shmem_get_partial_folio(inode, lstart >> PAGE_SHIFT);
953962
if (folio) {
@@ -973,6 +982,8 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, loff_t lend,
973982
folio_put(folio);
974983
}
975984

985+
whole_folios:
986+
976987
index = start;
977988
while (index < end) {
978989
cond_resched();

0 commit comments

Comments
 (0)