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

Commit 410fdc72 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Dave Chinner
Browse files

xfs: zero posteof blocks when cloning above eof



When we're reflinking between two files and the destination file range
is well beyond the destination file's EOF marker, zero any posteof
speculative preallocations in the destination file so that we don't
expose stale disk contents.  The previous strategy of trying to clear
the preallocations does not work if the destination file has the
PREALLOC flag set.

Uncovered by shared/010.

Reported-by: default avatarZorro Lang <zlang@redhat.com>
Bugzilla-id: https://bugzilla.kernel.org/show_bug.cgi?id=201259


Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 0d41e1d2
Loading
Loading
Loading
Loading
+25 −8
Original line number Diff line number Diff line
@@ -1240,6 +1240,26 @@ xfs_reflink_remap_unlock(
		inode_unlock_shared(inode_in);
}

/*
 * If we're reflinking to a point past the destination file's EOF, we must
 * zero any speculative post-EOF preallocations that sit between the old EOF
 * and the destination file offset.
 */
static int
xfs_reflink_zero_posteof(
	struct xfs_inode	*ip,
	loff_t			pos)
{
	loff_t			isize = i_size_read(VFS_I(ip));

	if (pos <= isize)
		return 0;

	trace_xfs_zero_eof(ip, isize, pos - isize);
	return iomap_zero_range(VFS_I(ip), isize, pos - isize, NULL,
			&xfs_iomap_ops);
}

/*
 * Prepare two files for range cloning.  Upon a successful return both inodes
 * will have the iolock and mmaplock held, the page cache of the out file
@@ -1292,15 +1312,12 @@ xfs_reflink_remap_prep(
		goto out_unlock;

	/*
	 * Clear out post-eof preallocations because we don't have page cache
	 * backing the delayed allocations and they'll never get freed on
	 * their own.
	 * Zero existing post-eof speculative preallocations in the destination
	 * file.
	 */
	if (xfs_can_free_eofblocks(dest, true)) {
		ret = xfs_free_eofblocks(dest);
	ret = xfs_reflink_zero_posteof(dest, pos_out);
	if (ret)
		goto out_unlock;
	}

	/* Set flags and remap blocks. */
	ret = xfs_reflink_set_inode_flag(src, dest);