From: Darrick J. Wong <djwong@xxxxxxxxxx> Copy the realtime rmapbt when we're metadumping the filesystem. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- db/metadump.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/db/metadump.c b/db/metadump.c index 15e3b302d61..e8663e11a3f 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -597,6 +597,54 @@ copy_rmap_btree( return scan_btree(agno, root, levels, TYP_RMAPBT, agf, scanfunc_rmapbt); } +static int +scanfunc_rtrmapbt( + struct xfs_btree_block *block, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + int level, + typnm_t btype, + void *arg) +{ + xfs_rtrmap_ptr_t *pp; + int i; + int numrecs; + + if (level == 0) + return 1; + + numrecs = be16_to_cpu(block->bb_numrecs); + if (numrecs > mp->m_rtrmap_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_rtrmap_ptr_addr(block, 1, mp->m_rtrmap_mxr[1]); + for (i = 0; i < numrecs; i++) { + xfs_agnumber_t pagno; + xfs_agblock_t pbno; + + pagno = XFS_FSB_TO_AGNO(mp, get_unaligned_be64(&pp[i])); + pbno = XFS_FSB_TO_AGBNO(mp, get_unaligned_be64(&pp[i])); + + if (pbno == 0 || pbno > mp->m_sb.sb_agblocks || + pagno > mp->m_sb.sb_agcount) { + if (show_warnings) + print_warning("invalid block number (%u/%u) " + "in inode %llu %s block %u/%u", + pagno, pbno, (long long)cur_ino, + typtab[btype].name, agno, agbno); + continue; + } + if (!scan_btree(pagno, pbno, level, btype, arg, + scanfunc_rtrmapbt)) + return 0; + } + return 1; +} + static int scanfunc_refcntbt( struct xfs_btree_block *block, @@ -2336,6 +2384,80 @@ process_exinode( whichfork), nex, itype, is_meta); } +static int +process_rtrmap( + struct xfs_dinode *dip, + typnm_t itype) +{ + struct xfs_rtrmap_root *dib; + int i; + xfs_rtrmap_ptr_t *pp; + int level; + int nrecs; + int maxrecs; + int whichfork; + typnm_t btype; + + if (itype == TYP_ATTR && show_warnings) { + print_warning("ignoring rtrmapbt root in inode %llu attr fork", + (long long)cur_ino); + return 1; + } + + whichfork = XFS_DATA_FORK; + btype = TYP_RTRMAPBT; + + dib = (struct xfs_rtrmap_root *)XFS_DFORK_PTR(dip, whichfork); + level = be16_to_cpu(dib->bb_level); + nrecs = be16_to_cpu(dib->bb_numrecs); + + if (level > mp->m_rtrmap_maxlevels) { + if (show_warnings) + print_warning("invalid level (%u) in inode %lld %s " + "root", level, (long long)cur_ino, + typtab[btype].name); + return 1; + } + + if (level == 0) + return 1; + + maxrecs = libxfs_rtrmapbt_droot_maxrecs( + XFS_DFORK_SIZE(dip, mp, whichfork), + false); + if (nrecs > maxrecs) { + if (show_warnings) + print_warning("invalid numrecs (%u) in inode %lld %s " + "root", nrecs, (long long)cur_ino, + typtab[btype].name); + return 1; + } + + pp = xfs_rtrmap_droot_ptr_addr(dib, 1, maxrecs); + for (i = 0; i < nrecs; i++) { + xfs_agnumber_t ag; + xfs_agblock_t bno; + + ag = XFS_FSB_TO_AGNO(mp, get_unaligned_be64(&pp[i])); + bno = XFS_FSB_TO_AGBNO(mp, get_unaligned_be64(&pp[i])); + + if (bno == 0 || bno > mp->m_sb.sb_agblocks || + ag > mp->m_sb.sb_agcount) { + if (show_warnings) + print_warning("invalid block number (%u/%u) " + "in inode %llu %s root", ag, + bno, (long long)cur_ino, + typtab[btype].name); + continue; + } + + if (!scan_btree(ag, bno, level, btype, &itype, + scanfunc_rtrmapbt)) + return 0; + } + return 1; +} + static int process_inode_data( struct xfs_dinode *dip, @@ -2380,6 +2502,9 @@ process_inode_data( case XFS_DINODE_FMT_BTREE: return process_btinode(dip, itype); + + case XFS_DINODE_FMT_RMAP: + return process_rtrmap(dip, itype); } return 1; }