Skip to content

Commit 514df14

Browse files
johnpgarryDarrick J. Wong
authored andcommitted
xfs: refactor xfs_reflink_end_cow_extent()
Refactor xfs_reflink_end_cow_extent() into separate parts which process the CoW range and commit the transaction. This refactoring will be used in future for when it is required to commit a range of extents as a single transaction, similar to how it was done pre-commit d6f215f. Reviewed-by: Darrick J. Wong <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]> Signed-off-by: John Garry <[email protected]>
1 parent 6baf4cc commit 514df14

File tree

1 file changed

+42
-30
lines changed

1 file changed

+42
-30
lines changed

fs/xfs/xfs_reflink.c

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -786,35 +786,19 @@ xfs_reflink_update_quota(
786786
* requirements as low as possible.
787787
*/
788788
STATIC int
789-
xfs_reflink_end_cow_extent(
789+
xfs_reflink_end_cow_extent_locked(
790+
struct xfs_trans *tp,
790791
struct xfs_inode *ip,
791792
xfs_fileoff_t *offset_fsb,
792793
xfs_fileoff_t end_fsb)
793794
{
794795
struct xfs_iext_cursor icur;
795796
struct xfs_bmbt_irec got, del, data;
796-
struct xfs_mount *mp = ip->i_mount;
797-
struct xfs_trans *tp;
798797
struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK);
799-
unsigned int resblks;
800798
int nmaps;
801799
bool isrt = XFS_IS_REALTIME_INODE(ip);
802800
int error;
803801

804-
resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
805-
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
806-
XFS_TRANS_RESERVE, &tp);
807-
if (error)
808-
return error;
809-
810-
/*
811-
* Lock the inode. We have to ijoin without automatic unlock because
812-
* the lead transaction is the refcountbt record deletion; the data
813-
* fork update follows as a deferred log item.
814-
*/
815-
xfs_ilock(ip, XFS_ILOCK_EXCL);
816-
xfs_trans_ijoin(tp, ip, 0);
817-
818802
/*
819803
* In case of racing, overlapping AIO writes no COW extents might be
820804
* left by the time I/O completes for the loser of the race. In that
@@ -823,7 +807,7 @@ xfs_reflink_end_cow_extent(
823807
if (!xfs_iext_lookup_extent(ip, ifp, *offset_fsb, &icur, &got) ||
824808
got.br_startoff >= end_fsb) {
825809
*offset_fsb = end_fsb;
826-
goto out_cancel;
810+
return 0;
827811
}
828812

829813
/*
@@ -837,7 +821,7 @@ xfs_reflink_end_cow_extent(
837821
if (!xfs_iext_next_extent(ifp, &icur, &got) ||
838822
got.br_startoff >= end_fsb) {
839823
*offset_fsb = end_fsb;
840-
goto out_cancel;
824+
return 0;
841825
}
842826
}
843827
del = got;
@@ -846,14 +830,14 @@ xfs_reflink_end_cow_extent(
846830
error = xfs_iext_count_extend(tp, ip, XFS_DATA_FORK,
847831
XFS_IEXT_REFLINK_END_COW_CNT);
848832
if (error)
849-
goto out_cancel;
833+
return error;
850834

851835
/* Grab the corresponding mapping in the data fork. */
852836
nmaps = 1;
853837
error = xfs_bmapi_read(ip, del.br_startoff, del.br_blockcount, &data,
854838
&nmaps, 0);
855839
if (error)
856-
goto out_cancel;
840+
return error;
857841

858842
/* We can only remap the smaller of the two extent sizes. */
859843
data.br_blockcount = min(data.br_blockcount, del.br_blockcount);
@@ -882,7 +866,7 @@ xfs_reflink_end_cow_extent(
882866
error = xfs_bunmapi(NULL, ip, data.br_startoff,
883867
data.br_blockcount, 0, 1, &done);
884868
if (error)
885-
goto out_cancel;
869+
return error;
886870
ASSERT(done);
887871
}
888872

@@ -899,17 +883,45 @@ xfs_reflink_end_cow_extent(
899883
/* Remove the mapping from the CoW fork. */
900884
xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
901885

902-
error = xfs_trans_commit(tp);
903-
xfs_iunlock(ip, XFS_ILOCK_EXCL);
904-
if (error)
905-
return error;
906-
907886
/* Update the caller about how much progress we made. */
908887
*offset_fsb = del.br_startoff + del.br_blockcount;
909888
return 0;
889+
}
910890

911-
out_cancel:
912-
xfs_trans_cancel(tp);
891+
/*
892+
* Remap part of the CoW fork into the data fork.
893+
*
894+
* We aim to remap the range starting at @offset_fsb and ending at @end_fsb
895+
* into the data fork; this function will remap what it can (at the end of the
896+
* range) and update @end_fsb appropriately. Each remap gets its own
897+
* transaction because we can end up merging and splitting bmbt blocks for
898+
* every remap operation and we'd like to keep the block reservation
899+
* requirements as low as possible.
900+
*/
901+
STATIC int
902+
xfs_reflink_end_cow_extent(
903+
struct xfs_inode *ip,
904+
xfs_fileoff_t *offset_fsb,
905+
xfs_fileoff_t end_fsb)
906+
{
907+
struct xfs_mount *mp = ip->i_mount;
908+
struct xfs_trans *tp;
909+
unsigned int resblks;
910+
int error;
911+
912+
resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
913+
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
914+
XFS_TRANS_RESERVE, &tp);
915+
if (error)
916+
return error;
917+
xfs_ilock(ip, XFS_ILOCK_EXCL);
918+
xfs_trans_ijoin(tp, ip, 0);
919+
920+
error = xfs_reflink_end_cow_extent_locked(tp, ip, offset_fsb, end_fsb);
921+
if (error)
922+
xfs_trans_cancel(tp);
923+
else
924+
error = xfs_trans_commit(tp);
913925
xfs_iunlock(ip, XFS_ILOCK_EXCL);
914926
return error;
915927
}

0 commit comments

Comments
 (0)