@@ -586,21 +586,21 @@ xfs_reflink_cancel_cow_range(
586586STATIC int
587587xfs_reflink_end_cow_extent (
588588 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 )
591591{
592- struct xfs_bmbt_irec got , del ;
593592 struct xfs_iext_cursor icur ;
593+ struct xfs_bmbt_irec got , del , data ;
594594 struct xfs_mount * mp = ip -> i_mount ;
595595 struct xfs_trans * tp ;
596596 struct xfs_ifork * ifp = XFS_IFORK_PTR (ip , XFS_COW_FORK );
597- xfs_filblks_t rlen ;
598597 unsigned int resblks ;
598+ int nmaps ;
599599 int error ;
600600
601601 /* No COW extents? That's easy! */
602602 if (ifp -> if_bytes == 0 ) {
603- * end_fsb = offset_fsb ;
603+ * offset_fsb = end_fsb ;
604604 return 0 ;
605605 }
606606
@@ -631,42 +631,66 @@ xfs_reflink_end_cow_extent(
631631 * left by the time I/O completes for the loser of the race. In that
632632 * case we are done.
633633 */
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 ;
637637 goto out_cancel ;
638638 }
639639
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-
651640 /*
652641 * Only remap real extents that contain data. With AIO, speculative
653642 * 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.
655646 */
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+ }
659653 }
654+ del = got ;
660655
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 );
664660 if (error )
665661 goto out_cancel ;
666662
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+ }
670694
671695 /* Free the CoW orphan record. */
672696 xfs_refcount_free_cow_extent (tp , del .br_startblock , del .br_blockcount );
@@ -687,7 +711,7 @@ xfs_reflink_end_cow_extent(
687711 return error ;
688712
689713 /* Update the caller about how much progress we made. */
690- * end_fsb = del .br_startoff ;
714+ * offset_fsb = del .br_startoff + del . br_blockcount ;
691715 return 0 ;
692716
693717out_cancel :
@@ -715,7 +739,7 @@ xfs_reflink_end_cow(
715739 end_fsb = XFS_B_TO_FSB (ip -> i_mount , offset + count );
716740
717741 /*
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
719743 * repeatedly cycles the ILOCK to allocate one transaction per remapped
720744 * extent.
721745 *
@@ -747,7 +771,7 @@ xfs_reflink_end_cow(
747771 * blocks will be remapped.
748772 */
749773 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 );
751775
752776 if (error )
753777 trace_xfs_reflink_end_cow_error (ip , error , _RET_IP_ );
0 commit comments