]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_db: copy the rmap btree
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 18 Aug 2016 23:39:03 +0000 (09:39 +1000)
committerDave Chinner <david@fromorbit.com>
Thu, 18 Aug 2016 23:39:03 +0000 (09:39 +1000)
Copy the rmapbt when we're metadumping the filesystem.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
db/metadump.c

index d7ff6e5ce2e801863f5f8389040185c5202d11ed..609a5d7bbbc6c949c99235f64c5b5df4f131de48 100644 (file)
@@ -543,6 +543,78 @@ copy_free_cnt_btree(
        return scan_btree(agno, root, levels, TYP_CNTBT, agf, scanfunc_freesp);
 }
 
+static int
+scanfunc_rmapbt(
+       struct xfs_btree_block  *block,
+       xfs_agnumber_t          agno,
+       xfs_agblock_t           agbno,
+       int                     level,
+       typnm_t                 btype,
+       void                    *arg)
+{
+       xfs_rmap_ptr_t          *pp;
+       int                     i;
+       int                     numrecs;
+
+       if (level == 0)
+               return 1;
+
+       numrecs = be16_to_cpu(block->bb_numrecs);
+       if (numrecs > mp->m_rmap_mxr[1]) {
+               if (show_warnings)
+                       print_warning("invalid numrecs (%u) in %s block %u/%u",
+                               numrecs, typtab[btype].name, agno, agbno);
+               return 1;
+       }
+
+       pp = XFS_RMAP_PTR_ADDR(block, 1, mp->m_rmap_mxr[1]);
+       for (i = 0; i < numrecs; i++) {
+               if (!valid_bno(agno, be32_to_cpu(pp[i]))) {
+                       if (show_warnings)
+                               print_warning("invalid block number (%u/%u) "
+                                       "in %s block %u/%u",
+                                       agno, be32_to_cpu(pp[i]),
+                                       typtab[btype].name, agno, agbno);
+                       continue;
+               }
+               if (!scan_btree(agno, be32_to_cpu(pp[i]), level, btype, arg,
+                               scanfunc_rmapbt))
+                       return 0;
+       }
+       return 1;
+}
+
+static int
+copy_rmap_btree(
+       xfs_agnumber_t  agno,
+       struct xfs_agf  *agf)
+{
+       xfs_agblock_t   root;
+       int             levels;
+
+       if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+               return 1;
+
+       root = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]);
+       levels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
+
+       /* validate root and levels before processing the tree */
+       if (root == 0 || root > mp->m_sb.sb_agblocks) {
+               if (show_warnings)
+                       print_warning("invalid block number (%u) in rmapbt "
+                                       "root in agf %u", root, agno);
+               return 1;
+       }
+       if (levels >= XFS_BTREE_MAXLEVELS) {
+               if (show_warnings)
+                       print_warning("invalid level (%u) in rmapbt root "
+                                       "in agf %u", levels, agno);
+               return 1;
+       }
+
+       return scan_btree(agno, root, levels, TYP_RMAPBT, agf, scanfunc_rmapbt);
+}
+
 /* filename and extended attribute obfuscation routines */
 
 struct name_ent {
@@ -2451,6 +2523,8 @@ scan_ag(
                        goto pop_out;
                if (!copy_free_cnt_btree(agno, agf))
                        goto pop_out;
+               if (!copy_rmap_btree(agno, agf))
+                       goto pop_out;
        }
 
        /* copy inode btrees and the inodes and their associated metadata */