summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2019-04-03 14:14:06 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2019-04-15 17:02:42 -0700
commita990a4e124e8aff76b5028326f598b65236529bd (patch)
treec7ed66bc85768800a5fe6f24329bd910717becb8
parentb881309db4de47440889252322a89e55121e92a1 (diff)
xfs: extend the range of flush_unmap rangesstale-exposure_2019-04-15
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 2db43ff4f8b5..eb219a7bb52b 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);