]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: ensure logflagsp is initialized in xfs_bmap_del_extent_real
authorJiachen Zhang <zhangjiachen.jaycee@bytedance.com>
Mon, 15 Apr 2024 23:07:35 +0000 (16:07 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 17 Apr 2024 21:06:24 +0000 (14:06 -0700)
Source kernel commit: e6af9c98cbf0164a619d95572136bfb54d482dd6

In the case of returning -ENOSPC, ensure logflagsp is initialized by 0.
Otherwise the caller __xfs_bunmapi will set uninitialized illegal
tmp_logflags value into xfs log, which might cause unpredictable error
in the log recovery procedure.

Also, remove the flags variable and set the *logflagsp directly, so that
the code should be more robust in the long run.

Fixes: 1b24b633aafe ("xfs: move some more code into xfs_bmap_del_extent_real")
Signed-off-by: Jiachen Zhang <zhangjiachen.jaycee@bytedance.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
Reviewed-by: Bill O'Donnell <bodonnel@redhat.com>
libxfs/xfs_bmap.c

index 8c553d22c535602f65b275f29ef4aea44a3e0c6e..20ec22dfcaf4ee1299b0bdcc1cb246e6e653a39c 100644 (file)
@@ -5004,7 +5004,6 @@ xfs_bmap_del_extent_real(
        xfs_fileoff_t           del_endoff;     /* first offset past del */
        int                     do_fx;  /* free extent at end of routine */
        int                     error;  /* error return value */
-       int                     flags = 0;/* inode logging flags */
        struct xfs_bmbt_irec    got;    /* current extent entry */
        xfs_fileoff_t           got_endoff;     /* first offset past got */
        int                     i;      /* temp state */
@@ -5017,6 +5016,8 @@ xfs_bmap_del_extent_real(
        uint32_t                state = xfs_bmap_fork_to_state(whichfork);
        struct xfs_bmbt_irec    old;
 
+       *logflagsp = 0;
+
        mp = ip->i_mount;
        XFS_STATS_INC(mp, xs_del_exlist);
 
@@ -5029,7 +5030,6 @@ xfs_bmap_del_extent_real(
        ASSERT(got_endoff >= del_endoff);
        ASSERT(!isnullstartblock(got.br_startblock));
        qfield = 0;
-       error = 0;
 
        /*
         * If it's the case where the directory code is running with no block
@@ -5045,13 +5045,13 @@ xfs_bmap_del_extent_real(
            del->br_startoff > got.br_startoff && del_endoff < got_endoff)
                return -ENOSPC;
 
-       flags = XFS_ILOG_CORE;
+       *logflagsp = XFS_ILOG_CORE;
        if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
                if (!(bflags & XFS_BMAPI_REMAP)) {
                        error = xfs_rtfree_blocks(tp, del->br_startblock,
                                        del->br_blockcount);
                        if (error)
-                               goto done;
+                               return error;
                }
 
                do_fx = 0;
@@ -5066,11 +5066,9 @@ xfs_bmap_del_extent_real(
        if (cur) {
                error = xfs_bmbt_lookup_eq(cur, &got, &i);
                if (error)
-                       goto done;
-               if (XFS_IS_CORRUPT(mp, i != 1)) {
-                       error = -EFSCORRUPTED;
-                       goto done;
-               }
+                       return error;
+               if (XFS_IS_CORRUPT(mp, i != 1))
+                       return -EFSCORRUPTED;
        }
 
        if (got.br_startoff == del->br_startoff)
@@ -5087,17 +5085,15 @@ xfs_bmap_del_extent_real(
                xfs_iext_prev(ifp, icur);
                ifp->if_nextents--;
 
-               flags |= XFS_ILOG_CORE;
+               *logflagsp |= XFS_ILOG_CORE;
                if (!cur) {
-                       flags |= xfs_ilog_fext(whichfork);
+                       *logflagsp |= xfs_ilog_fext(whichfork);
                        break;
                }
                if ((error = xfs_btree_delete(cur, &i)))
-                       goto done;
-               if (XFS_IS_CORRUPT(mp, i != 1)) {
-                       error = -EFSCORRUPTED;
-                       goto done;
-               }
+                       return error;
+               if (XFS_IS_CORRUPT(mp, i != 1))
+                       return -EFSCORRUPTED;
                break;
        case BMAP_LEFT_FILLING:
                /*
@@ -5108,12 +5104,12 @@ xfs_bmap_del_extent_real(
                got.br_blockcount -= del->br_blockcount;
                xfs_iext_update_extent(ip, state, icur, &got);
                if (!cur) {
-                       flags |= xfs_ilog_fext(whichfork);
+                       *logflagsp |= xfs_ilog_fext(whichfork);
                        break;
                }
                error = xfs_bmbt_update(cur, &got);
                if (error)
-                       goto done;
+                       return error;
                break;
        case BMAP_RIGHT_FILLING:
                /*
@@ -5122,12 +5118,12 @@ xfs_bmap_del_extent_real(
                got.br_blockcount -= del->br_blockcount;
                xfs_iext_update_extent(ip, state, icur, &got);
                if (!cur) {
-                       flags |= xfs_ilog_fext(whichfork);
+                       *logflagsp |= xfs_ilog_fext(whichfork);
                        break;
                }
                error = xfs_bmbt_update(cur, &got);
                if (error)
-                       goto done;
+                       return error;
                break;
        case 0:
                /*
@@ -5144,18 +5140,18 @@ xfs_bmap_del_extent_real(
                new.br_state = got.br_state;
                new.br_startblock = del_endblock;
 
-               flags |= XFS_ILOG_CORE;
+               *logflagsp |= XFS_ILOG_CORE;
                if (cur) {
                        error = xfs_bmbt_update(cur, &got);
                        if (error)
-                               goto done;
+                               return error;
                        error = xfs_btree_increment(cur, 0, &i);
                        if (error)
-                               goto done;
+                               return error;
                        cur->bc_rec.b = new;
                        error = xfs_btree_insert(cur, &i);
                        if (error && error != -ENOSPC)
-                               goto done;
+                               return error;
                        /*
                         * If get no-space back from btree insert, it tried a
                         * split, and we have a zero block reservation.  Fix up
@@ -5168,33 +5164,28 @@ xfs_bmap_del_extent_real(
                                 */
                                error = xfs_bmbt_lookup_eq(cur, &got, &i);
                                if (error)
-                                       goto done;
-                               if (XFS_IS_CORRUPT(mp, i != 1)) {
-                                       error = -EFSCORRUPTED;
-                                       goto done;
-                               }
+                                       return error;
+                               if (XFS_IS_CORRUPT(mp, i != 1))
+                                       return -EFSCORRUPTED;
                                /*
                                 * Update the btree record back
                                 * to the original value.
                                 */
                                error = xfs_bmbt_update(cur, &old);
                                if (error)
-                                       goto done;
+                                       return error;
                                /*
                                 * Reset the extent record back
                                 * to the original value.
                                 */
                                xfs_iext_update_extent(ip, state, icur, &old);
-                               flags = 0;
-                               error = -ENOSPC;
-                               goto done;
-                       }
-                       if (XFS_IS_CORRUPT(mp, i != 1)) {
-                               error = -EFSCORRUPTED;
-                               goto done;
+                               *logflagsp = 0;
+                               return -ENOSPC;
                        }
+                       if (XFS_IS_CORRUPT(mp, i != 1))
+                               return -EFSCORRUPTED;
                } else
-                       flags |= xfs_ilog_fext(whichfork);
+                       *logflagsp |= xfs_ilog_fext(whichfork);
 
                ifp->if_nextents++;
                xfs_iext_next(ifp, icur);
@@ -5218,7 +5209,7 @@ xfs_bmap_del_extent_real(
                                        ((bflags & XFS_BMAPI_NODISCARD) ||
                                        del->br_state == XFS_EXT_UNWRITTEN));
                        if (error)
-                               goto done;
+                               return error;
                }
        }
 
@@ -5233,9 +5224,7 @@ xfs_bmap_del_extent_real(
        if (qfield && !(bflags & XFS_BMAPI_REMAP))
                xfs_trans_mod_dquot_byino(tp, ip, qfield, (long)-nblks);
 
-done:
-       *logflagsp = flags;
-       return error;
+       return 0;
 }
 
 /*