]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - libxfs/xfs_da_btree.c
xfs: factor xfs_da3_blkinfo verification into common helper
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_da_btree.c
index cd66272df7fdc97b8d08a90b74ca17c0c8a4b192..eb45b774b00cb85a41b0395bfca924e0aa2a2ea5 100644 (file)
@@ -111,6 +111,34 @@ xfs_da_state_free(xfs_da_state_t *state)
        kmem_zone_free(xfs_da_state_zone, state);
 }
 
+/*
+ * Verify an xfs_da3_blkinfo structure. Note that the da3 fields are only
+ * accessible on v5 filesystems. This header format is common across da node,
+ * attr leaf and dir leaf blocks.
+ */
+xfs_failaddr_t
+xfs_da3_blkinfo_verify(
+       struct xfs_buf          *bp,
+       struct xfs_da3_blkinfo  *hdr3)
+{
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
+       struct xfs_da_blkinfo   *hdr = &hdr3->hdr;
+
+       if (!xfs_verify_magic(bp, hdr->magic))
+               return __this_address;
+
+       if (xfs_sb_version_hascrc(&mp->m_sb)) {
+               if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
+                       return __this_address;
+               if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
+                       return __this_address;
+               if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
+                       return __this_address;
+       }
+
+       return 0;
+}
+
 static xfs_failaddr_t
 xfs_da3_node_verify(
        struct xfs_buf          *bp)
@@ -119,27 +147,16 @@ xfs_da3_node_verify(
        struct xfs_da_intnode   *hdr = bp->b_addr;
        struct xfs_da3_icnode_hdr ichdr;
        const struct xfs_dir_ops *ops;
+       xfs_failaddr_t          fa;
 
        ops = xfs_dir_get_ops(mp, NULL);
 
        ops->node_hdr_from_disk(&ichdr, hdr);
 
-       if (xfs_sb_version_hascrc(&mp->m_sb)) {
-               struct xfs_da3_node_hdr *hdr3 = bp->b_addr;
-
-               if (ichdr.magic != XFS_DA3_NODE_MAGIC)
-                       return __this_address;
+       fa = xfs_da3_blkinfo_verify(bp, bp->b_addr);
+       if (fa)
+               return fa;
 
-               if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid))
-                       return __this_address;
-               if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn)
-                       return __this_address;
-               if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->info.lsn)))
-                       return __this_address;
-       } else {
-               if (ichdr.magic != XFS_DA_NODE_MAGIC)
-                       return __this_address;
-       }
        if (ichdr.level == 0)
                return __this_address;
        if (ichdr.level > XFS_DA_NODE_MAXDEPTH)
@@ -252,6 +269,8 @@ xfs_da3_node_verify_struct(
 
 const struct xfs_buf_ops xfs_da3_node_buf_ops = {
        .name = "xfs_da3_node",
+       .magic = { cpu_to_be16(XFS_DA_NODE_MAGIC),
+                  cpu_to_be16(XFS_DA3_NODE_MAGIC) },
        .verify_read = xfs_da3_node_read_verify,
        .verify_write = xfs_da3_node_write_verify,
        .verify_struct = xfs_da3_node_verify_struct,
@@ -1476,6 +1495,7 @@ xfs_da3_node_lookup_int(
        int                     error;
        int                     retval;
        unsigned int            expected_level = 0;
+       uint16_t                magic;
        struct xfs_inode        *dp = state->args->dp;
 
        args = state->args;
@@ -1500,25 +1520,27 @@ xfs_da3_node_lookup_int(
                        return error;
                }
                curr = blk->bp->b_addr;
-               blk->magic = be16_to_cpu(curr->magic);
+               magic = be16_to_cpu(curr->magic);
 
-               if (blk->magic == XFS_ATTR_LEAF_MAGIC ||
-                   blk->magic == XFS_ATTR3_LEAF_MAGIC) {
+               if (magic == XFS_ATTR_LEAF_MAGIC ||
+                   magic == XFS_ATTR3_LEAF_MAGIC) {
                        blk->magic = XFS_ATTR_LEAF_MAGIC;
                        blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
                        break;
                }
 
-               if (blk->magic == XFS_DIR2_LEAFN_MAGIC ||
-                   blk->magic == XFS_DIR3_LEAFN_MAGIC) {
+               if (magic == XFS_DIR2_LEAFN_MAGIC ||
+                   magic == XFS_DIR3_LEAFN_MAGIC) {
                        blk->magic = XFS_DIR2_LEAFN_MAGIC;
                        blk->hashval = xfs_dir2_leaf_lasthash(args->dp,
                                                              blk->bp, NULL);
                        break;
                }
 
-               blk->magic = XFS_DA_NODE_MAGIC;
+               if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC)
+                       return -EFSCORRUPTED;
 
+               blk->magic = XFS_DA_NODE_MAGIC;
 
                /*
                 * Search an intermediate node for a match.
@@ -2054,10 +2076,9 @@ xfs_da_grow_inode_int(
         * Try mapping it in one filesystem block.
         */
        nmap = 1;
-       ASSERT(args->firstblock != NULL);
        error = xfs_bmapi_write(tp, dp, *bno, count,
                        xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
-                       args->firstblock, args->total, &map, &nmap);
+                       args->total, &map, &nmap);
        if (error)
                return error;
 
@@ -2079,8 +2100,7 @@ xfs_da_grow_inode_int(
                        c = (int)(*bno + count - b);
                        error = xfs_bmapi_write(tp, dp, b, c,
                                        xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA,
-                                       args->firstblock, args->total,
-                                       &mapp[mapi], &nmap);
+                                       args->total, &mapp[mapi], &nmap);
                        if (error)
                                goto out_free_map;
                        if (nmap < 1)
@@ -2389,8 +2409,7 @@ xfs_da_shrink_inode(
                 * the last block to the place we want to kill.
                 */
                error = xfs_bunmapi(tp, dp, dead_blkno, count,
-                                   xfs_bmapi_aflag(w), 0, args->firstblock,
-                                   &done);
+                                   xfs_bmapi_aflag(w), 0, &done);
                if (error == -ENOSPC) {
                        if (w != XFS_DATA_FORK)
                                break;