Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5f3f959 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Dave Chinner
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent f369a13c
Loading
Loading
Loading
Loading
+4 −6
Original line number Original line Diff line number Diff line
@@ -693,14 +693,12 @@ xfs_reflink_end_cow(
		if (!del.br_blockcount)
		if (!del.br_blockcount)
			goto prev_extent;
			goto prev_extent;


		ASSERT(!isnullstartblock(got.br_startblock));

		/*
		/*
		 * Don't remap unwritten extents; these are
		 * Only remap real extent that contain data.  With AIO
		 * speculatively preallocated CoW extents that have been
		 * speculatively preallocations can leak into the range we
		 * allocated but have not yet been involved in a write.
		 * are called upon, and we need to skip them.
		 */
		 */
		if (got.br_state == XFS_EXT_UNWRITTEN)
		if (!xfs_bmap_is_real_extent(&got))
			goto prev_extent;
			goto prev_extent;


		/* Unmap the old blocks in the data fork. */
		/* Unmap the old blocks in the data fork. */