@@ -786,35 +786,19 @@ xfs_reflink_update_quota(
786
786
* requirements as low as possible.
787
787
*/
788
788
STATIC int
789
- xfs_reflink_end_cow_extent (
789
+ xfs_reflink_end_cow_extent_locked (
790
+ struct xfs_trans * tp ,
790
791
struct xfs_inode * ip ,
791
792
xfs_fileoff_t * offset_fsb ,
792
793
xfs_fileoff_t end_fsb )
793
794
{
794
795
struct xfs_iext_cursor icur ;
795
796
struct xfs_bmbt_irec got , del , data ;
796
- struct xfs_mount * mp = ip -> i_mount ;
797
- struct xfs_trans * tp ;
798
797
struct xfs_ifork * ifp = xfs_ifork_ptr (ip , XFS_COW_FORK );
799
- unsigned int resblks ;
800
798
int nmaps ;
801
799
bool isrt = XFS_IS_REALTIME_INODE (ip );
802
800
int error ;
803
801
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
-
818
802
/*
819
803
* In case of racing, overlapping AIO writes no COW extents might be
820
804
* left by the time I/O completes for the loser of the race. In that
@@ -823,7 +807,7 @@ xfs_reflink_end_cow_extent(
823
807
if (!xfs_iext_lookup_extent (ip , ifp , * offset_fsb , & icur , & got ) ||
824
808
got .br_startoff >= end_fsb ) {
825
809
* offset_fsb = end_fsb ;
826
- goto out_cancel ;
810
+ return 0 ;
827
811
}
828
812
829
813
/*
@@ -837,7 +821,7 @@ xfs_reflink_end_cow_extent(
837
821
if (!xfs_iext_next_extent (ifp , & icur , & got ) ||
838
822
got .br_startoff >= end_fsb ) {
839
823
* offset_fsb = end_fsb ;
840
- goto out_cancel ;
824
+ return 0 ;
841
825
}
842
826
}
843
827
del = got ;
@@ -846,14 +830,14 @@ xfs_reflink_end_cow_extent(
846
830
error = xfs_iext_count_extend (tp , ip , XFS_DATA_FORK ,
847
831
XFS_IEXT_REFLINK_END_COW_CNT );
848
832
if (error )
849
- goto out_cancel ;
833
+ return error ;
850
834
851
835
/* Grab the corresponding mapping in the data fork. */
852
836
nmaps = 1 ;
853
837
error = xfs_bmapi_read (ip , del .br_startoff , del .br_blockcount , & data ,
854
838
& nmaps , 0 );
855
839
if (error )
856
- goto out_cancel ;
840
+ return error ;
857
841
858
842
/* We can only remap the smaller of the two extent sizes. */
859
843
data .br_blockcount = min (data .br_blockcount , del .br_blockcount );
@@ -882,7 +866,7 @@ xfs_reflink_end_cow_extent(
882
866
error = xfs_bunmapi (NULL , ip , data .br_startoff ,
883
867
data .br_blockcount , 0 , 1 , & done );
884
868
if (error )
885
- goto out_cancel ;
869
+ return error ;
886
870
ASSERT (done );
887
871
}
888
872
@@ -899,17 +883,45 @@ xfs_reflink_end_cow_extent(
899
883
/* Remove the mapping from the CoW fork. */
900
884
xfs_bmap_del_extent_cow (ip , & icur , & got , & del );
901
885
902
- error = xfs_trans_commit (tp );
903
- xfs_iunlock (ip , XFS_ILOCK_EXCL );
904
- if (error )
905
- return error ;
906
-
907
886
/* Update the caller about how much progress we made. */
908
887
* offset_fsb = del .br_startoff + del .br_blockcount ;
909
888
return 0 ;
889
+ }
910
890
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 );
913
925
xfs_iunlock (ip , XFS_ILOCK_EXCL );
914
926
return error ;
915
927
}
0 commit comments