@@ -786,35 +786,19 @@ xfs_reflink_update_quota(
786786 * requirements as low as possible.
787787 */
788788STATIC 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