xfs: split xfs_bmap_shift_extents
authorChristoph Hellwig <hch@lst.de>
Thu, 19 Oct 2017 18:07:11 +0000 (11:07 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Thu, 26 Oct 2017 22:38:27 +0000 (15:38 -0700)
Have a separate helper for insert vs collapse, as this prepares us for
simplifying the code in the next patches.

Also changed the done output argument to a bool intead of int for both
new functions.

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/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_bmap.h
fs/xfs/xfs_bmap_util.c

index d0118a2..47fb517 100644 (file)
@@ -5700,57 +5700,151 @@ update_current_ext:
        return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &new);
 }
 
-/*
- * Shift extent records to the left/right to cover/create a hole.
- *
- * @stop_fsb specifies the file offset at which to stop shift and the
- * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb
- * is the length by which each extent is shifted. If there is no hole to shift
- * the extents into, this will be considered invalid operation and we abort
- * immediately.
- */
 int
-xfs_bmap_shift_extents(
+xfs_bmap_collapse_extents(
        struct xfs_trans        *tp,
        struct xfs_inode        *ip,
        xfs_fileoff_t           *next_fsb,
        xfs_fileoff_t           offset_shift_fsb,
-       int                     *done,
+       bool                    *done,
        xfs_fileoff_t           stop_fsb,
        xfs_fsblock_t           *firstblock,
-       struct xfs_defer_ops    *dfops,
-       enum shift_direction    direction)
+       struct xfs_defer_ops    *dfops)
 {
-       struct xfs_btree_cur            *cur = NULL;
-       struct xfs_bmbt_irec            got;
-       struct xfs_mount                *mp = ip->i_mount;
-       struct xfs_ifork                *ifp;
-       xfs_extnum_t                    current_ext;
-       xfs_extnum_t                    total_extents;
-       xfs_extnum_t                    stop_extent;
-       int                             error = 0;
-       int                             whichfork = XFS_DATA_FORK;
-       int                             logflags = 0;
+       int                     whichfork = XFS_DATA_FORK;
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_btree_cur    *cur = NULL;
+       struct xfs_bmbt_irec    got;
+       xfs_extnum_t            current_ext;
+       xfs_extnum_t            total_extents;
+       xfs_extnum_t            stop_extent;
+       int                     error = 0;
+       int                     logflags = 0;
 
        if (unlikely(XFS_TEST_ERROR(
            (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
             XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
             mp, XFS_ERRTAG_BMAPIFORMAT))) {
-               XFS_ERROR_REPORT("xfs_bmap_shift_extents",
-                                XFS_ERRLEVEL_LOW, mp);
+               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
                return -EFSCORRUPTED;
        }
 
        if (XFS_FORCED_SHUTDOWN(mp))
                return -EIO;
 
-       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
-       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-       ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT);
+       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL));
+
+       if (!(ifp->if_flags & XFS_IFEXTENTS)) {
+               error = xfs_iread_extents(tp, ip, whichfork);
+               if (error)
+                       return error;
+       }
+
+       if (ifp->if_flags & XFS_IFBROOT) {
+               cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
+               cur->bc_private.b.firstblock = *firstblock;
+               cur->bc_private.b.dfops = dfops;
+               cur->bc_private.b.flags = 0;
+       }
+
+       /*
+        * There may be delalloc extents in the data fork before the range we
+        * are collapsing out, so we cannot use the count of real extents here.
+        * Instead we have to calculate it from the incore fork.
+        */
+       total_extents = xfs_iext_count(ifp);
+       if (total_extents == 0) {
+               *done = true;
+               goto del_cursor;
+       }
+
+       /*
+        * Look up the extent index for the fsb where we start shifting. We can
+        * henceforth iterate with current_ext as extent list changes are locked
+        * out via ilock.
+        *
+        * If next_fsb lies in a hole beyond which there are no extents we are
+        * done.
+        */
+       if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, &current_ext, &got)) {
+               *done = true;
+               goto del_cursor;
+       }
+
+       stop_extent = total_extents;
+       if (current_ext >= stop_extent) {
+               error = -EIO;
+               goto del_cursor;
+       }
+
+       error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
+                                  &current_ext, &got, cur, &logflags,
+                                  SHIFT_LEFT, dfops);
+       if (error)
+               goto del_cursor;
+       /*
+        * If there was an extent merge during the shift, the extent
+        * count can change. Update the total and grade the next record.
+        */
+       total_extents = xfs_iext_count(ifp);
+       stop_extent = total_extents;
+       if (current_ext == stop_extent) {
+               *done = true;
+               goto del_cursor;
+       }
+       xfs_iext_get_extent(ifp, current_ext, &got);
+
+       if (!*done)
+               *next_fsb = got.br_startoff;
+
+del_cursor:
+       if (cur)
+               xfs_btree_del_cursor(cur,
+                       error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+
+       if (logflags)
+               xfs_trans_log_inode(tp, ip, logflags);
+
+       return error;
+}
+
+int
+xfs_bmap_insert_extents(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *ip,
+       xfs_fileoff_t           *next_fsb,
+       xfs_fileoff_t           offset_shift_fsb,
+       bool                    *done,
+       xfs_fileoff_t           stop_fsb,
+       xfs_fsblock_t           *firstblock,
+       struct xfs_defer_ops    *dfops)
+{
+       int                     whichfork = XFS_DATA_FORK;
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, whichfork);
+       struct xfs_btree_cur    *cur = NULL;
+       struct xfs_bmbt_irec    got, s;
+       xfs_extnum_t            current_ext;
+       xfs_extnum_t            total_extents;
+       xfs_extnum_t            stop_extent;
+       int                     error = 0;
+       int                     logflags = 0;
+
+       if (unlikely(XFS_TEST_ERROR(
+           (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
+            XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
+            mp, XFS_ERRTAG_BMAPIFORMAT))) {
+               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
+               return -EFSCORRUPTED;
+       }
+
+       if (XFS_FORCED_SHUTDOWN(mp))
+               return -EIO;
+
+       ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL));
 
-       ifp = XFS_IFORK_PTR(ip, whichfork);
        if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-               /* Read in all the extents */
                error = xfs_iread_extents(tp, ip, whichfork);
                if (error)
                        return error;
@@ -5770,7 +5864,7 @@ xfs_bmap_shift_extents(
         */
        total_extents = xfs_iext_count(ifp);
        if (total_extents == 0) {
-               *done = 1;
+               *done = true;
                goto del_cursor;
        }
 
@@ -5778,12 +5872,10 @@ xfs_bmap_shift_extents(
         * In case of first right shift, we need to initialize next_fsb
         */
        if (*next_fsb == NULLFSBLOCK) {
-               ASSERT(direction == SHIFT_RIGHT);
-
                current_ext = total_extents - 1;
                xfs_iext_get_extent(ifp, current_ext, &got);
                if (stop_fsb > got.br_startoff) {
-                       *done = 1;
+                       *done = true;
                        goto del_cursor;
                }
                *next_fsb = got.br_startoff;
@@ -5798,46 +5890,27 @@ xfs_bmap_shift_extents(
                 */
                if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, &current_ext,
                                &got)) {
-                       *done = 1;
+                       *done = true;
                        goto del_cursor;
                }
        }
 
        /* Lookup the extent index at which we have to stop */
-       if (direction == SHIFT_RIGHT) {
-               struct xfs_bmbt_irec s;
-
-               xfs_iext_lookup_extent(ip, ifp, stop_fsb, &stop_extent, &s);
-               /* Make stop_extent exclusive of shift range */
-               stop_extent--;
-               if (current_ext <= stop_extent) {
-                       error = -EIO;
-                       goto del_cursor;
-               }
-       } else {
-               stop_extent = total_extents;
-               if (current_ext >= stop_extent) {
-                       error = -EIO;
-                       goto del_cursor;
-               }
+       xfs_iext_lookup_extent(ip, ifp, stop_fsb, &stop_extent, &s);
+       /* Make stop_extent exclusive of shift range */
+       stop_extent--;
+       if (current_ext <= stop_extent) {
+               error = -EIO;
+               goto del_cursor;
        }
 
        error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
                                   &current_ext, &got, cur, &logflags,
-                                  direction, dfops);
+                                  SHIFT_RIGHT, dfops);
        if (error)
                goto del_cursor;
-       /*
-        * If there was an extent merge during the shift, the extent
-        * count can change. Update the total and grade the next record.
-        */
-       if (direction == SHIFT_LEFT) {
-               total_extents = xfs_iext_count(ifp);
-               stop_extent = total_extents;
-       }
-
        if (current_ext == stop_extent) {
-               *done = 1;
+               *done = true;
                goto del_cursor;
        }
        xfs_iext_get_extent(ifp, current_ext, &got);
index ba5a483..ca37030 100644 (file)
@@ -228,10 +228,14 @@ int       xfs_bmap_del_extent_delay(struct xfs_inode *ip, int whichfork,
 void   xfs_bmap_del_extent_cow(struct xfs_inode *ip, xfs_extnum_t *idx,
                struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del);
 uint   xfs_default_attroffset(struct xfs_inode *ip);
-int    xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
+int    xfs_bmap_collapse_extents(struct xfs_trans *tp, struct xfs_inode *ip,
                xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
-               int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock,
-               struct xfs_defer_ops *dfops, enum shift_direction direction);
+               bool *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock,
+               struct xfs_defer_ops *dfops);
+int    xfs_bmap_insert_extents(struct xfs_trans *tp, struct xfs_inode *ip,
+               xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
+               bool *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock,
+               struct xfs_defer_ops *dfops);
 int    xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset);
 int    xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
                xfs_fileoff_t off, xfs_filblks_t len, xfs_filblks_t prealloc,
index 3273f08..034f342 100644 (file)
@@ -1322,7 +1322,6 @@ xfs_collapse_file_space(
        xfs_off_t               offset,
        xfs_off_t               len)
 {
-       int                     done = 0;
        struct xfs_mount        *mp = ip->i_mount;
        struct xfs_trans        *tp;
        int                     error;
@@ -1332,6 +1331,7 @@ xfs_collapse_file_space(
        xfs_fileoff_t           next_fsb = XFS_B_TO_FSB(mp, offset + len);
        xfs_fileoff_t           shift_fsb = XFS_B_TO_FSB(mp, len);
        uint                    resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+       bool                    done = false;
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
        trace_xfs_collapse_file_space(ip);
@@ -1359,9 +1359,8 @@ xfs_collapse_file_space(
                xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 
                xfs_defer_init(&dfops, &first_block);
-               error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb,
-                               &done, stop_fsb, &first_block, &dfops,
-                               SHIFT_LEFT);
+               error = xfs_bmap_collapse_extents(tp, ip, &next_fsb, shift_fsb,
+                               &done, stop_fsb, &first_block, &dfops);
                if (error)
                        goto out_bmap_cancel;
 
@@ -1406,7 +1405,7 @@ xfs_insert_file_space(
        xfs_fileoff_t           stop_fsb = XFS_B_TO_FSB(mp, offset);
        xfs_fileoff_t           next_fsb = NULLFSBLOCK;
        xfs_fileoff_t           shift_fsb = XFS_B_TO_FSB(mp, len);
-       int                     done = 0;
+       bool                    done = false;
 
        ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
        trace_xfs_insert_file_space(ip);
@@ -1433,9 +1432,8 @@ xfs_insert_file_space(
                xfs_ilock(ip, XFS_ILOCK_EXCL);
                xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
                xfs_defer_init(&dfops, &first_block);
-               error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb,
-                               &done, stop_fsb, &first_block, &dfops,
-                               SHIFT_RIGHT);
+               error = xfs_bmap_insert_extents(tp, ip, &next_fsb, shift_fsb,
+                               &done, stop_fsb, &first_block, &dfops);
                if (error)
                        goto out_bmap_cancel;