summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-05-21 17:07:06 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-06-26 13:01:53 -0700
commit6ec1e0013f4ffc21917ea4ac5cb53c47f9c6f581 (patch)
tree1de9e77bd01c9163166e439904518627f67204e2
parent793d96c09a600b5ce773007cc433cfdcf1df10ba (diff)
xfs: extend the range of flush_unmap rangesstale-exposure_2019-06-26
If we have to initiate writeback of a range that starts beyond the on-disk EOF, extend the flushed range to start at the on-disk EOF so that there's no chance that we put real extents in the data fork having not actually flushed the data. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/xfs_bmap_util.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index b8fa6d337413..5ab912ce38bd 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1050,7 +1050,7 @@ xfs_flush_unmap_range(
{
struct xfs_mount *mp = ip->i_mount;
struct inode *inode = VFS_I(ip);
- xfs_off_t rounding, start, end;
+ xfs_off_t rounding, start, end, flush_start;
int error;
/* wait for the completion of any pending DIOs */
@@ -1060,7 +1060,20 @@ xfs_flush_unmap_range(
start = round_down(offset, rounding);
end = round_up(offset + len, rounding) - 1;
- error = filemap_write_and_wait_range(inode->i_mapping, start, end);
+ /*
+ * If we begin a data integrity writeback of a range that starts beyond
+ * the on-disk EOF, it's possible that we'll convert an entire delalloc
+ * extent to real to satisfy the writeback. The on-disk EOF will be
+ * updated to @offset + @len once writeback completes, having written
+ * the entire real extent record into the data fork. This is a vector
+ * for exposure of stale disk contents, so we begin the flush at the
+ * on-disk EOF or the requested range start, whichever is smaller.
+ */
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
+ flush_start = min(start, ip->i_d.di_size);
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ error = filemap_write_and_wait_range(inode->i_mapping, flush_start,
+ end);
if (error)
return error;
truncate_pagecache_range(inode, start, end);