xfs: hoist recovered rmap intent checks out of xfs_rui_item_recover
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 30 Nov 2020 00:33:36 +0000 (16:33 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Wed, 9 Dec 2020 17:49:38 +0000 (09:49 -0800)
When we recover a rmap intent from the log, we need to validate its
contents before we try to replay them.  Hoist the checking code into a
separate function in preparation to refactor this code to use validation
helpers.

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

index 7adc996ca6e3010ab30d508df31635c02db7d75a..19d2dc285ed6a5454bcea32dd3c8540d18885f2d 100644 (file)
@@ -460,6 +460,42 @@ const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
        .cancel_item    = xfs_rmap_update_cancel_item,
 };
 
+/* Is this recovered RUI ok? */
+static inline bool
+xfs_rui_validate_map(
+       struct xfs_mount                *mp,
+       struct xfs_map_extent           *rmap)
+{
+       xfs_fsblock_t                   startblock_fsb;
+       bool                            op_ok;
+
+       startblock_fsb = XFS_BB_TO_FSB(mp,
+                          XFS_FSB_TO_DADDR(mp, rmap->me_startblock));
+       switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
+       case XFS_RMAP_EXTENT_MAP:
+       case XFS_RMAP_EXTENT_MAP_SHARED:
+       case XFS_RMAP_EXTENT_UNMAP:
+       case XFS_RMAP_EXTENT_UNMAP_SHARED:
+       case XFS_RMAP_EXTENT_CONVERT:
+       case XFS_RMAP_EXTENT_CONVERT_SHARED:
+       case XFS_RMAP_EXTENT_ALLOC:
+       case XFS_RMAP_EXTENT_FREE:
+               op_ok = true;
+               break;
+       default:
+               op_ok = false;
+               break;
+       }
+       if (!op_ok || startblock_fsb == 0 ||
+           rmap->me_len == 0 ||
+           startblock_fsb >= mp->m_sb.sb_dblocks ||
+           rmap->me_len >= mp->m_sb.sb_agblocks ||
+           (rmap->me_flags & ~XFS_RMAP_EXTENT_FLAGS))
+               return false;
+
+       return true;
+}
+
 /*
  * Process an rmap update intent item that was recovered from the log.
  * We need to update the rmapbt.
@@ -475,10 +511,8 @@ xfs_rui_item_recover(
        struct xfs_trans                *tp;
        struct xfs_btree_cur            *rcur = NULL;
        struct xfs_mount                *mp = lip->li_mountp;
-       xfs_fsblock_t                   startblock_fsb;
        enum xfs_rmap_intent_type       type;
        xfs_exntst_t                    state;
-       bool                            op_ok;
        int                             i;
        int                             whichfork;
        int                             error = 0;
@@ -489,30 +523,13 @@ xfs_rui_item_recover(
         * just toss the RUI.
         */
        for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
-               rmap = &ruip->rui_format.rui_extents[i];
-               startblock_fsb = XFS_BB_TO_FSB(mp,
-                                  XFS_FSB_TO_DADDR(mp, rmap->me_startblock));
-               switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
-               case XFS_RMAP_EXTENT_MAP:
-               case XFS_RMAP_EXTENT_MAP_SHARED:
-               case XFS_RMAP_EXTENT_UNMAP:
-               case XFS_RMAP_EXTENT_UNMAP_SHARED:
-               case XFS_RMAP_EXTENT_CONVERT:
-               case XFS_RMAP_EXTENT_CONVERT_SHARED:
-               case XFS_RMAP_EXTENT_ALLOC:
-               case XFS_RMAP_EXTENT_FREE:
-                       op_ok = true;
-                       break;
-               default:
-                       op_ok = false;
-                       break;
-               }
-               if (!op_ok || startblock_fsb == 0 ||
-                   rmap->me_len == 0 ||
-                   startblock_fsb >= mp->m_sb.sb_dblocks ||
-                   rmap->me_len >= mp->m_sb.sb_agblocks ||
-                   (rmap->me_flags & ~XFS_RMAP_EXTENT_FLAGS))
+               if (!xfs_rui_validate_map(mp,
+                                       &ruip->rui_format.rui_extents[i])) {
+                       XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                                       &ruip->rui_format,
+                                       sizeof(ruip->rui_format));
                        return -EFSCORRUPTED;
+               }
        }
 
        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate,