]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_db: copy the realtime rmap btree
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:22:21 +0000 (14:22 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 9 Jul 2024 22:37:20 +0000 (15:37 -0700)
Copy the realtime rmapbt when we're metadumping the filesystem.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
db/metadump.c

index b39c6016272c4335e57d9d9742b6d25cf003c658..b34952524e74b3c54b4c41be45ca62c8dd3bbf9b 100644 (file)
@@ -589,6 +589,55 @@ 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 (metadump.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 (metadump.show_warnings)
+                               print_warning("invalid block number (%u/%u) "
+                                               "in inode %llu %s block %u/%u",
+                                               pagno, pbno,
+                                               (unsigned long long)metadump.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,
@@ -2302,6 +2351,83 @@ 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 && metadump.show_warnings) {
+               print_warning("ignoring rtrmapbt root in inode %llu attr fork",
+                               (unsigned long long)metadump.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 (metadump.show_warnings)
+                       print_warning("invalid level (%u) in inode %lld %s "
+                                       "root", level,
+                                       (unsigned long long)metadump.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 (metadump.show_warnings)
+                       print_warning("invalid numrecs (%u) in inode %lld %s "
+                                       "root", nrecs,
+                                       (unsigned long long)metadump.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 (metadump.show_warnings)
+                               print_warning("invalid block number (%u/%u) "
+                                               "in inode %llu %s root", ag,
+                                               bno,
+                                               (unsigned long long)metadump.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,
@@ -2346,6 +2472,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;
 }