aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-10-05 05:04:27 -0400
committerDave Chinner <david@fromorbit.com>2018-10-05 05:04:27 -0400
commit410fdc72b05afabef3afb51167085799dcc7b3cf (patch)
treeb47c895971b7fd030a4b0ba3e0503fd1f7f8c274 /fs/xfs
parent0d41e1d28c2e969094ef7933b8521f1e08d30251 (diff)
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: Zorro Lang <zlang@redhat.com> Bugzilla-id: https://bugzilla.kernel.org/show_bug.cgi?id=201259 Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_reflink.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index da1a447bef51..f135748d8282 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1241,6 +1241,26 @@ xfs_reflink_remap_unlock(
1241} 1241}
1242 1242
1243/* 1243/*
1244 * If we're reflinking to a point past the destination file's EOF, we must
1245 * zero any speculative post-EOF preallocations that sit between the old EOF
1246 * and the destination file offset.
1247 */
1248static int
1249xfs_reflink_zero_posteof(
1250 struct xfs_inode *ip,
1251 loff_t pos)
1252{
1253 loff_t isize = i_size_read(VFS_I(ip));
1254
1255 if (pos <= isize)
1256 return 0;
1257
1258 trace_xfs_zero_eof(ip, isize, pos - isize);
1259 return iomap_zero_range(VFS_I(ip), isize, pos - isize, NULL,
1260 &xfs_iomap_ops);
1261}
1262
1263/*
1244 * Prepare two files for range cloning. Upon a successful return both inodes 1264 * Prepare two files for range cloning. Upon a successful return both inodes
1245 * will have the iolock and mmaplock held, the page cache of the out file 1265 * will have the iolock and mmaplock held, the page cache of the out file
1246 * will be truncated, and any leases on the out file will have been broken. 1266 * will be truncated, and any leases on the out file will have been broken.
@@ -1292,15 +1312,12 @@ xfs_reflink_remap_prep(
1292 goto out_unlock; 1312 goto out_unlock;
1293 1313
1294 /* 1314 /*
1295 * Clear out post-eof preallocations because we don't have page cache 1315 * Zero existing post-eof speculative preallocations in the destination
1296 * backing the delayed allocations and they'll never get freed on 1316 * file.
1297 * their own.
1298 */ 1317 */
1299 if (xfs_can_free_eofblocks(dest, true)) { 1318 ret = xfs_reflink_zero_posteof(dest, pos_out);
1300 ret = xfs_free_eofblocks(dest); 1319 if (ret)
1301 if (ret) 1320 goto out_unlock;
1302 goto out_unlock;
1303 }
1304 1321
1305 /* Set flags and remap blocks. */ 1322 /* Set flags and remap blocks. */
1306 ret = xfs_reflink_set_inode_flag(src, dest); 1323 ret = xfs_reflink_set_inode_flag(src, dest);