xfs: hoist recovered refcount intent checks out of xfs_cui_item_recover
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 30 Nov 2020 00:33:37 +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 refcount 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_refcount_item.c

index 7529eb63ce947349b3bcd71974d2159ac28d6bb7..e19f96c9b93a2dc17ca6015bdb7e7d8dadf96688 100644 (file)
@@ -417,6 +417,38 @@ const struct xfs_defer_op_type xfs_refcount_update_defer_type = {
        .cancel_item    = xfs_refcount_update_cancel_item,
 };
 
+/* Is this recovered CUI ok? */
+static inline bool
+xfs_cui_validate_phys(
+       struct xfs_mount                *mp,
+       struct xfs_phys_extent          *refc)
+{
+       xfs_fsblock_t                   startblock_fsb;
+       bool                            op_ok;
+
+       startblock_fsb = XFS_BB_TO_FSB(mp,
+                          XFS_FSB_TO_DADDR(mp, refc->pe_startblock));
+       switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) {
+       case XFS_REFCOUNT_INCREASE:
+       case XFS_REFCOUNT_DECREASE:
+       case XFS_REFCOUNT_ALLOC_COW:
+       case XFS_REFCOUNT_FREE_COW:
+               op_ok = true;
+               break;
+       default:
+               op_ok = false;
+               break;
+       }
+       if (!op_ok || startblock_fsb == 0 ||
+           refc->pe_len == 0 ||
+           startblock_fsb >= mp->m_sb.sb_dblocks ||
+           refc->pe_len >= mp->m_sb.sb_agblocks ||
+           (refc->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS))
+               return false;
+
+       return true;
+}
+
 /*
  * Process a refcount update intent item that was recovered from the log.
  * We need to update the refcountbt.
@@ -433,11 +465,9 @@ xfs_cui_item_recover(
        struct xfs_trans                *tp;
        struct xfs_btree_cur            *rcur = NULL;
        struct xfs_mount                *mp = lip->li_mountp;
-       xfs_fsblock_t                   startblock_fsb;
        xfs_fsblock_t                   new_fsb;
        xfs_extlen_t                    new_len;
        unsigned int                    refc_type;
-       bool                            op_ok;
        bool                            requeue_only = false;
        enum xfs_refcount_intent_type   type;
        int                             i;
@@ -449,26 +479,13 @@ xfs_cui_item_recover(
         * just toss the CUI.
         */
        for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
-               refc = &cuip->cui_format.cui_extents[i];
-               startblock_fsb = XFS_BB_TO_FSB(mp,
-                                  XFS_FSB_TO_DADDR(mp, refc->pe_startblock));
-               switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) {
-               case XFS_REFCOUNT_INCREASE:
-               case XFS_REFCOUNT_DECREASE:
-               case XFS_REFCOUNT_ALLOC_COW:
-               case XFS_REFCOUNT_FREE_COW:
-                       op_ok = true;
-                       break;
-               default:
-                       op_ok = false;
-                       break;
-               }
-               if (!op_ok || startblock_fsb == 0 ||
-                   refc->pe_len == 0 ||
-                   startblock_fsb >= mp->m_sb.sb_dblocks ||
-                   refc->pe_len >= mp->m_sb.sb_agblocks ||
-                   (refc->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS))
+               if (!xfs_cui_validate_phys(mp,
+                                       &cuip->cui_format.cui_extents[i])) {
+                       XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                                       &cuip->cui_format,
+                                       sizeof(cuip->cui_format));
                        return -EFSCORRUPTED;
+               }
        }
 
        /*