xfs: iterate backwards in xfs_reflink_cancel_cow_blocks
authorChristoph Hellwig <hch@lst.de>
Fri, 3 Nov 2017 17:34:44 +0000 (10:34 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 6 Nov 2017 19:53:40 +0000 (11:53 -0800)
Match the iteration order for extent deletion in the truncate and
reflink I/O completion path.

This also happens to make implementing the new incore extent list
a lot easier.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/xfs_reflink.c

index d86c437..cf976ed 100644 (file)
@@ -569,12 +569,20 @@ xfs_reflink_cancel_cow_blocks(
 
        if (!xfs_is_reflink_inode(ip))
                return 0;
-       if (!xfs_iext_lookup_extent(ip, ifp, offset_fsb, &icur, &got))
+       if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got))
                return 0;
 
-       while (got.br_startoff < end_fsb) {
+       /* Walk backwards until we're out of the I/O range... */
+       while (got.br_startoff + got.br_blockcount > offset_fsb) {
                del = got;
                xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb);
+
+               /* Extent delete may have bumped ext forward */
+               if (!del.br_blockcount) {
+                       xfs_iext_prev(ifp, &icur);
+                       goto next_extent;
+               }
+
                trace_xfs_reflink_cancel_cow(ip, &del);
 
                if (isnullstartblock(del.br_startblock)) {
@@ -612,8 +620,8 @@ xfs_reflink_cancel_cow_blocks(
                        /* Remove the mapping from the CoW fork. */
                        xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
                }
-
-               if (!xfs_iext_next_extent(ifp, &icur, &got))
+next_extent:
+               if (!xfs_iext_get_extent(ifp, &icur, &got))
                        break;
        }