From e434854e45f34594479461efd13fa461be4376b5 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 19 Aug 2016 09:39:03 +1000 Subject: [PATCH] xfs_db: copy the rmap btree Copy the rmapbt when we're metadumping the filesystem. Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- db/metadump.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/db/metadump.c b/db/metadump.c index d7ff6e5ce..609a5d7bb 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -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 */ -- 2.39.2