aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-09-28 23:49:58 -0400
committerDave Chinner <david@fromorbit.com>2018-09-28 23:49:58 -0400
commitf5f3f959b70b272dfe2d05758e43ae52f5ff7748 (patch)
tree993379f5bd715a61485c0ac9f966464222977151
parentf369a13cead821e679c7415dc66a17ec48cc26bf (diff)
xfs: skip delalloc COW blocks in xfs_reflink_end_cow
The iomap direct I/O code issues a single ->end_io call for the whole I/O request, and if some of the extents cowered needed a COW operation it will call xfs_reflink_end_cow over the whole range. When we do AIO writes we drop the iolock after doing the initial setup, but before the I/O completion. Between dropping the lock and completing the I/O we can have a racing buffered write create new delalloc COW fork extents in the region covered by the outstanding direct I/O write, and thus see delalloc COW fork extents in xfs_reflink_end_cow. As concurrent writes are fundamentally racy and no guarantees are given we can simply skip those. This can be easily reproduced with xfstests generic/208 in always_cow mode. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--fs/xfs/xfs_reflink.c10
1 files changed, 4 insertions, 6 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index d60d0eeed7b9..5289e22cb081 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -693,14 +693,12 @@ xfs_reflink_end_cow(
693 if (!del.br_blockcount) 693 if (!del.br_blockcount)
694 goto prev_extent; 694 goto prev_extent;
695 695
696 ASSERT(!isnullstartblock(got.br_startblock));
697
698 /* 696 /*
699 * Don't remap unwritten extents; these are 697 * Only remap real extent that contain data. With AIO
700 * speculatively preallocated CoW extents that have been 698 * speculatively preallocations can leak into the range we
701 * allocated but have not yet been involved in a write. 699 * are called upon, and we need to skip them.
702 */ 700 */
703 if (got.br_state == XFS_EXT_UNWRITTEN) 701 if (!xfs_bmap_is_real_extent(&got))
704 goto prev_extent; 702 goto prev_extent;
705 703
706 /* Unmap the old blocks in the data fork. */ 704 /* Unmap the old blocks in the data fork. */