diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2019-05-21 17:07:06 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-08-10 09:57:55 -0700 |
commit | 3de8c3f110514cf8024f9952a4166a5900f68c1b (patch) | |
tree | 4354f08d3fc74d12a92453513ca85b163c29db6a | |
parent | 74567793356854cd392c8bea4e517388d27ae8f9 (diff) |
xfs: extend the range of flush_unmap rangesstale-exposure_2019-08-10
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.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 98c6a7a71427..64bdee48fad4 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1045,7 +1045,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 */ @@ -1055,7 +1055,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); |