summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-08-30 15:44:38 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-10-28 21:00:36 -0700
commite3e550e3083f184fbae9be02ba3d89cca10c43d5 (patch)
tree55287306ca0dc531c7b047e66aa28d8dbbaee70f
parente32305be59f0fad5cf67b7ffec7e20af604433b1 (diff)
xfs: extend the range of flush_unmap rangesstale-exposure_2019-10-28
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 2dd49fb6794e..a40cca0d8b2f 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -937,7 +937,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 */
@@ -947,7 +947,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);