diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2020-06-30 00:47:19 +0300 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2020-07-06 20:46:57 +0300 |
commit | 168eae803cede459d67ed0ab3ddb19539700a78a (patch) | |
tree | 70cfe01a8b1fdc5c1f382bd34da529911308256c /fs | |
parent | 94b941fd7a98cebd6b77b8925c54ef76bbf7473f (diff) | |
download | linux-168eae803cede459d67ed0ab3ddb19539700a78a.tar.xz |
xfs: reflink can skip remap existing mappings
If the source and destination map are identical, we can skip the remap
step to save some time.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_reflink.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 35a17ca5b508..0a3681646fc9 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1035,6 +1035,22 @@ xfs_reflink_remap_extent( trace_xfs_reflink_remap_extent_dest(ip, &smap); + /* + * Two extents mapped to the same physical block must not have + * different states; that's filesystem corruption. Move on to the next + * extent if they're both holes or both the same physical extent. + */ + if (dmap->br_startblock == smap.br_startblock) { + if (dmap->br_state != smap.br_state) + error = -EFSCORRUPTED; + goto out_cancel; + } + + /* If both extents are unwritten, leave them alone. */ + if (dmap->br_state == XFS_EXT_UNWRITTEN && + smap.br_state == XFS_EXT_UNWRITTEN) + goto out_cancel; + /* No reflinking if the AG of the dest mapping is low on space. */ if (dmap_written) { error = xfs_reflink_ag_has_free_space(mp, |