]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - libxfs/xfs_da_btree.c
xfs: explicitly pass buffer size to xfs_corruption_error
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_da_btree.c
index b2457fdc58d099605e9d442c075964385766cfbf..467e96dc9e350522b3435fe6cf84991cb3415946 100644 (file)
@@ -123,7 +123,7 @@ xfs_da_state_free(xfs_da_state_t *state)
        kmem_zone_free(xfs_da_state_zone, state);
 }
 
-static bool
+static xfs_failaddr_t
 xfs_da3_node_verify(
        struct xfs_buf          *bp)
 {
@@ -140,24 +140,24 @@ xfs_da3_node_verify(
                struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
 
                if (ichdr.magic != XFS_DA3_NODE_MAGIC)
-                       return false;
+                       return __this_address;
 
                if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid))
-                       return false;
+                       return __this_address;
                if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn)
-                       return false;
+                       return __this_address;
                if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->info.lsn)))
-                       return false;
+                       return __this_address;
        } else {
                if (ichdr.magic != XFS_DA_NODE_MAGIC)
-                       return false;
+                       return __this_address;
        }
        if (ichdr.level == 0)
-               return false;
+               return __this_address;
        if (ichdr.level > XFS_DA_NODE_MAXDEPTH)
-               return false;
+               return __this_address;
        if (ichdr.count == 0)
-               return false;
+               return __this_address;
 
        /*
         * we don't know if the node is for and attribute or directory tree,
@@ -165,11 +165,11 @@ xfs_da3_node_verify(
         */
        if (ichdr.count > mp->m_dir_geo->node_ents &&
            ichdr.count > mp->m_attr_geo->node_ents)
-               return false;
+               return __this_address;
 
        /* XXX: hash order check? */
 
-       return true;
+       return NULL;
 }
 
 static void
@@ -177,12 +177,13 @@ xfs_da3_node_write_verify(
        struct xfs_buf  *bp)
 {
        struct xfs_mount        *mp = bp->b_target->bt_mount;
-       struct xfs_buf_log_item *bip = bp->b_fspriv;
+       struct xfs_buf_log_item *bip = bp->b_log_item;
        struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
+       xfs_failaddr_t          fa;
 
-       if (!xfs_da3_node_verify(bp)) {
-               xfs_buf_ioerror(bp, -EFSCORRUPTED);
-               xfs_verifier_error(bp);
+       fa = xfs_da3_node_verify(bp);
+       if (fa) {
+               xfs_verifier_error(bp, -EFSCORRUPTED, fa);
                return;
        }
 
@@ -206,19 +207,20 @@ xfs_da3_node_read_verify(
        struct xfs_buf          *bp)
 {
        struct xfs_da_blkinfo   *info = bp->b_addr;
+       xfs_failaddr_t          fa;
 
        switch (be16_to_cpu(info->magic)) {
                case XFS_DA3_NODE_MAGIC:
                        if (!xfs_buf_verify_cksum(bp, XFS_DA3_NODE_CRC_OFF)) {
-                               xfs_buf_ioerror(bp, -EFSBADCRC);
+                               xfs_verifier_error(bp, -EFSBADCRC,
+                                               __this_address);
                                break;
                        }
                        /* fall through */
                case XFS_DA_NODE_MAGIC:
-                       if (!xfs_da3_node_verify(bp)) {
-                               xfs_buf_ioerror(bp, -EFSCORRUPTED);
-                               break;
-                       }
+                       fa = xfs_da3_node_verify(bp);
+                       if (fa)
+                               xfs_verifier_error(bp, -EFSCORRUPTED, fa);
                        return;
                case XFS_ATTR_LEAF_MAGIC:
                case XFS_ATTR3_LEAF_MAGIC:
@@ -231,18 +233,40 @@ xfs_da3_node_read_verify(
                        bp->b_ops->verify_read(bp);
                        return;
                default:
-                       xfs_buf_ioerror(bp, -EFSCORRUPTED);
+                       xfs_verifier_error(bp, -EFSCORRUPTED, __this_address);
                        break;
        }
+}
+
+/* Verify the structure of a da3 block. */
+static xfs_failaddr_t
+xfs_da3_node_verify_struct(
+       struct xfs_buf          *bp)
+{
+       struct xfs_da_blkinfo   *info = bp->b_addr;
 
-       /* corrupt block */
-       xfs_verifier_error(bp);
+       switch (be16_to_cpu(info->magic)) {
+       case XFS_DA3_NODE_MAGIC:
+       case XFS_DA_NODE_MAGIC:
+               return xfs_da3_node_verify(bp);
+       case XFS_ATTR_LEAF_MAGIC:
+       case XFS_ATTR3_LEAF_MAGIC:
+               bp->b_ops = &xfs_attr3_leaf_buf_ops;
+               return bp->b_ops->verify_struct(bp);
+       case XFS_DIR2_LEAFN_MAGIC:
+       case XFS_DIR3_LEAFN_MAGIC:
+               bp->b_ops = &xfs_dir3_leafn_buf_ops;
+               return bp->b_ops->verify_struct(bp);
+       default:
+               return __this_address;
+       }
 }
 
 const struct xfs_buf_ops xfs_da3_node_buf_ops = {
        .name = "xfs_da3_node",
        .verify_read = xfs_da3_node_read_verify,
        .verify_write = xfs_da3_node_write_verify,
+       .verify_struct = xfs_da3_node_verify_struct,
 };
 
 int
@@ -276,9 +300,11 @@ xfs_da3_node_read(
                        type = XFS_BLFT_DIR_LEAFN_BUF;
                        break;
                default:
-                       type = 0;
-                       ASSERT(0);
-                       break;
+                       XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
+                                       tp->t_mountp, info, sizeof(*info));
+                       xfs_trans_brelse(tp, *bpp);
+                       *bpp = NULL;
+                       return -EFSCORRUPTED;
                }
                xfs_trans_buf_set_type(tp, *bpp, type);
        }