Remapping an extent involves unmapping the existing extent and mapping in the new extent. When unmapping, an extent containing the entire unmap range can be split into two extents, i.e. | Old extent | hole | Old extent | Hence extent count increases by 1. Mapping in the new extent into the destination file can increase the extent count by 1. Signed-off-by: Chandan Babu R <chandanrlinux@xxxxxxxxx> --- fs/xfs/libxfs/xfs_inode_fork.h | 15 +++++++++++++++ fs/xfs/xfs_reflink.c | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h index d750bdff17c9..afff20703270 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.h +++ b/fs/xfs/libxfs/xfs_inode_fork.h @@ -85,6 +85,21 @@ struct xfs_ifork { * Hence number of extents increases by 2. */ #define XFS_IEXT_REFLINK_END_COW_CNT 2 +/* + * Remapping an extent involves unmapping the existing extent and + * mapping in the new extent. + * When unmapping, an extent containing the entire unmap + * range can be split into two extents, + * i.e. | Old extent | hole | Old extent | + * Hence extent count increases by 1. + * + * Mapping in the new extent into the destination file can increase + * the extent count by 1. + */ +#define XFS_IEXT_REFLINK_REMAP_CNT(smap_real, dmap_written) \ + (((smap_real) ? 1 : 0) + ((dmap_written) ? 1 : 0)) + + /* * Fork handling. */ diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 04a7754ee681..134d49f8c941 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1100,6 +1100,11 @@ xfs_reflink_remap_extent( goto out_cancel; } + error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, + XFS_IEXT_REFLINK_REMAP_CNT(smap_real, dmap_written)); + if (error) + goto out_cancel; + if (smap_real) { /* * If the extent we're unmapping is backed by storage (written -- 2.28.0