summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_file.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 7918968e1d62..845a97c9b063 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1306,6 +1306,23 @@ xfs_falloc_insert_range(
if (offset >= isize)
return -EINVAL;
+ /*
+ * Let writeback clean up EOF folio state before we bump i_size. The
+ * insert flushes before it starts shifting and under certain
+ * circumstances we can write back blocks that should technically be
+ * considered post-eof (and thus should not be submitted for writeback).
+ *
+ * For example, a large, dirty folio that spans EOF and is backed by
+ * post-eof COW fork preallocation can cause block remap into the data
+ * fork. This shifts back out beyond EOF, but creates an expectedly
+ * written post-eof block. The insert is going to flush, unmap and
+ * cancel prealloc across this whole range, so flush EOF now before we
+ * bump i_size to provide consistent behavior.
+ */
+ error = filemap_write_and_wait_range(inode->i_mapping, isize, isize);
+ if (error)
+ return error;
+
error = xfs_falloc_setsize(file, isize + len);
if (error)
return error;