@@ -586,21 +586,21 @@ xfs_reflink_cancel_cow_range(
586
586
STATIC int
587
587
xfs_reflink_end_cow_extent (
588
588
struct xfs_inode * ip ,
589
- xfs_fileoff_t offset_fsb ,
590
- xfs_fileoff_t * end_fsb )
589
+ xfs_fileoff_t * offset_fsb ,
590
+ xfs_fileoff_t end_fsb )
591
591
{
592
- struct xfs_bmbt_irec got , del ;
593
592
struct xfs_iext_cursor icur ;
593
+ struct xfs_bmbt_irec got , del , data ;
594
594
struct xfs_mount * mp = ip -> i_mount ;
595
595
struct xfs_trans * tp ;
596
596
struct xfs_ifork * ifp = XFS_IFORK_PTR (ip , XFS_COW_FORK );
597
- xfs_filblks_t rlen ;
598
597
unsigned int resblks ;
598
+ int nmaps ;
599
599
int error ;
600
600
601
601
/* No COW extents? That's easy! */
602
602
if (ifp -> if_bytes == 0 ) {
603
- * end_fsb = offset_fsb ;
603
+ * offset_fsb = end_fsb ;
604
604
return 0 ;
605
605
}
606
606
@@ -631,42 +631,66 @@ xfs_reflink_end_cow_extent(
631
631
* left by the time I/O completes for the loser of the race. In that
632
632
* case we are done.
633
633
*/
634
- if (!xfs_iext_lookup_extent_before (ip , ifp , end_fsb , & icur , & got ) ||
635
- got .br_startoff + got . br_blockcount <= offset_fsb ) {
636
- * end_fsb = offset_fsb ;
634
+ if (!xfs_iext_lookup_extent (ip , ifp , * offset_fsb , & icur , & got ) ||
635
+ got .br_startoff >= end_fsb ) {
636
+ * offset_fsb = end_fsb ;
637
637
goto out_cancel ;
638
638
}
639
639
640
- /*
641
- * Structure copy @got into @del, then trim @del to the range that we
642
- * were asked to remap. We preserve @got for the eventual CoW fork
643
- * deletion; from now on @del represents the mapping that we're
644
- * actually remapping.
645
- */
646
- del = got ;
647
- xfs_trim_extent (& del , offset_fsb , * end_fsb - offset_fsb );
648
-
649
- ASSERT (del .br_blockcount > 0 );
650
-
651
640
/*
652
641
* Only remap real extents that contain data. With AIO, speculative
653
642
* preallocations can leak into the range we are called upon, and we
654
- * need to skip them.
643
+ * need to skip them. Preserve @got for the eventual CoW fork
644
+ * deletion; from now on @del represents the mapping that we're
645
+ * actually remapping.
655
646
*/
656
- if (!xfs_bmap_is_written_extent (& got )) {
657
- * end_fsb = del .br_startoff ;
658
- goto out_cancel ;
647
+ while (!xfs_bmap_is_written_extent (& got )) {
648
+ if (!xfs_iext_next_extent (ifp , & icur , & got ) ||
649
+ got .br_startoff >= end_fsb ) {
650
+ * offset_fsb = end_fsb ;
651
+ goto out_cancel ;
652
+ }
659
653
}
654
+ del = got ;
660
655
661
- /* Unmap the old blocks in the data fork. */
662
- rlen = del .br_blockcount ;
663
- error = __xfs_bunmapi (tp , ip , del .br_startoff , & rlen , 0 , 1 );
656
+ /* Grab the corresponding mapping in the data fork. */
657
+ nmaps = 1 ;
658
+ error = xfs_bmapi_read (ip , del .br_startoff , del .br_blockcount , & data ,
659
+ & nmaps , 0 );
664
660
if (error )
665
661
goto out_cancel ;
666
662
667
- /* Trim the extent to whatever got unmapped. */
668
- xfs_trim_extent (& del , del .br_startoff + rlen , del .br_blockcount - rlen );
669
- trace_xfs_reflink_cow_remap (ip , & del );
663
+ /* We can only remap the smaller of the two extent sizes. */
664
+ data .br_blockcount = min (data .br_blockcount , del .br_blockcount );
665
+ del .br_blockcount = data .br_blockcount ;
666
+
667
+ trace_xfs_reflink_cow_remap_from (ip , & del );
668
+ trace_xfs_reflink_cow_remap_to (ip , & data );
669
+
670
+ if (xfs_bmap_is_real_extent (& data )) {
671
+ /*
672
+ * If the extent we're remapping is backed by storage (written
673
+ * or not), unmap the extent and drop its refcount.
674
+ */
675
+ xfs_bmap_unmap_extent (tp , ip , & data );
676
+ xfs_refcount_decrease_extent (tp , & data );
677
+ xfs_trans_mod_dquot_byino (tp , ip , XFS_TRANS_DQ_BCOUNT ,
678
+ - data .br_blockcount );
679
+ } else if (data .br_startblock == DELAYSTARTBLOCK ) {
680
+ int done ;
681
+
682
+ /*
683
+ * If the extent we're remapping is a delalloc reservation,
684
+ * we can use the regular bunmapi function to release the
685
+ * incore state. Dropping the delalloc reservation takes care
686
+ * of the quota reservation for us.
687
+ */
688
+ error = xfs_bunmapi (NULL , ip , data .br_startoff ,
689
+ data .br_blockcount , 0 , 1 , & done );
690
+ if (error )
691
+ goto out_cancel ;
692
+ ASSERT (done );
693
+ }
670
694
671
695
/* Free the CoW orphan record. */
672
696
xfs_refcount_free_cow_extent (tp , del .br_startblock , del .br_blockcount );
@@ -687,7 +711,7 @@ xfs_reflink_end_cow_extent(
687
711
return error ;
688
712
689
713
/* Update the caller about how much progress we made. */
690
- * end_fsb = del .br_startoff ;
714
+ * offset_fsb = del .br_startoff + del . br_blockcount ;
691
715
return 0 ;
692
716
693
717
out_cancel :
@@ -715,7 +739,7 @@ xfs_reflink_end_cow(
715
739
end_fsb = XFS_B_TO_FSB (ip -> i_mount , offset + count );
716
740
717
741
/*
718
- * Walk backwards until we're out of the I/O range. The loop function
742
+ * Walk forwards until we've remapped the I/O range. The loop function
719
743
* repeatedly cycles the ILOCK to allocate one transaction per remapped
720
744
* extent.
721
745
*
@@ -747,7 +771,7 @@ xfs_reflink_end_cow(
747
771
* blocks will be remapped.
748
772
*/
749
773
while (end_fsb > offset_fsb && !error )
750
- error = xfs_reflink_end_cow_extent (ip , offset_fsb , & end_fsb );
774
+ error = xfs_reflink_end_cow_extent (ip , & offset_fsb , end_fsb );
751
775
752
776
if (error )
753
777
trace_xfs_reflink_end_cow_error (ip , error , _RET_IP_ );
0 commit comments