]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_db: make fsmap query the realtime reverse mapping tree
authorDarrick J. Wong <djwong@kernel.org>
Thu, 15 Aug 2024 18:57:37 +0000 (11:57 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 16 Aug 2024 21:57:41 +0000 (14:57 -0700)
Extend the 'fsmap' debugger command to support querying the realtime
rmap btree via a new -r argument.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
db/fsmap.c
libxfs/libxfs_api_defs.h

index 7fd42df2a1c8547c3cd27582fe24acdcba2c0746..97d13bd4e2d6a48a50a3f8dbc1de271df5ea1644 100644 (file)
@@ -102,6 +102,135 @@ fsmap(
        }
 }
 
+static int
+fsmap_rt_fn(
+       struct xfs_btree_cur            *cur,
+       const struct xfs_rmap_irec      *rec,
+       void                            *priv)
+{
+       struct fsmap_info               *info = priv;
+
+       dbprintf(_("%llu: %u/%u len %u owner %lld offset %llu bmbt %d attrfork %d extflag %d\n"),
+               info->nr, cur->bc_ino.rtg->rtg_rgno, rec->rm_startblock,
+               rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
+               !!(rec->rm_flags & XFS_RMAP_BMBT_BLOCK),
+               !!(rec->rm_flags & XFS_RMAP_ATTR_FORK),
+               !!(rec->rm_flags & XFS_RMAP_UNWRITTEN));
+       info->nr++;
+
+       return 0;
+}
+
+static int
+fsmap_rtgroup(
+       struct xfs_rtgroup              *rtg,
+       const struct xfs_rmap_irec      *low,
+       const struct xfs_rmap_irec      *high,
+       struct fsmap_info               *info)
+{
+       struct xfs_mount        *mp = rtg->rtg_mount;
+       struct xfs_trans        *tp;
+       struct xfs_btree_cur    *bt_cur;
+       int                     error;
+
+       error = -libxfs_trans_alloc_empty(mp, &tp);
+       if (error) {
+               dbprintf(
+ _("Cannot alloc transaction to look up rtgroup %u rmap inode\n"),
+                               rtg->rtg_rgno);
+               return error;
+       }
+
+       error = -libxfs_rtginode_load_parent(tp);
+       if (error) {
+               dbprintf(_("Cannot load realtime metadir, error %d\n"),
+                       error);
+               goto out_trans;
+       }
+
+       error = -libxfs_rtginode_load(rtg, XFS_RTGI_RMAP, tp);
+       if (error) {
+               dbprintf(_("Cannot load rtgroup %u rmap inode, error %d\n"),
+                       rtg->rtg_rgno, error);
+               goto out_rele_dp;
+       }
+
+       bt_cur = libxfs_rtrmapbt_init_cursor(mp, tp, rtg,
+                       rtg->rtg_inodes[XFS_RTGI_RMAP]);
+       if (!bt_cur) {
+               dbprintf(_("Not enough memory.\n"));
+               goto out_rele_ip;
+       }
+
+       error = -libxfs_rmap_query_range(bt_cur, low, high, fsmap_rt_fn,
+                       info);
+       if (error) {
+               dbprintf(_("Error %d while querying rt fsmap btree.\n"),
+                       error);
+               goto out_cur;
+       }
+
+out_cur:
+       libxfs_btree_del_cursor(bt_cur, error);
+out_rele_ip:
+       libxfs_rtginode_irele(&rtg->rtg_inodes[XFS_RTGI_RMAP]);
+out_rele_dp:
+       libxfs_rtginode_irele(&mp->m_rtdirip);
+out_trans:
+       libxfs_trans_cancel(tp);
+       return error;
+}
+
+static void
+fsmap_rt(
+       xfs_fsblock_t           start_fsb,
+       xfs_fsblock_t           end_fsb)
+{
+       struct fsmap_info       info;
+       xfs_daddr_t             eofs;
+       struct xfs_rmap_irec    low;
+       struct xfs_rmap_irec    high;
+       struct xfs_rtgroup      *rtg;
+       xfs_rgnumber_t          start_rg;
+       xfs_rgnumber_t          end_rg;
+       int                     error;
+
+       if (mp->m_sb.sb_rblocks == 0)
+               return;
+
+       eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
+       if (XFS_FSB_TO_DADDR(mp, end_fsb) >= eofs)
+               end_fsb = XFS_DADDR_TO_FSB(mp, eofs - 1);
+
+       low.rm_startblock = xfs_rtb_to_rgbno(mp, start_fsb);
+       low.rm_owner = 0;
+       low.rm_offset = 0;
+       low.rm_flags = 0;
+       high.rm_startblock = -1U;
+       high.rm_owner = ULLONG_MAX;
+       high.rm_offset = ULLONG_MAX;
+       high.rm_flags = XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK |
+                       XFS_RMAP_UNWRITTEN;
+
+       start_rg = xfs_rtb_to_rgno(mp, start_fsb);
+       end_rg = xfs_rtb_to_rgno(mp, end_fsb);
+
+       info.nr = 0;
+       for_each_rtgroup_range(mp, start_rg, end_rg, rtg) {
+               if (rtg->rtg_rgno == end_rg)
+                       high.rm_startblock = xfs_rtb_to_rgbno(mp, end_fsb);
+
+               error = fsmap_rtgroup(rtg, &low, &high, &info);
+               if (error) {
+                       libxfs_rtgroup_put(rtg);
+                       return;
+               }
+
+               if (rtg->rtg_rgno == start_rg)
+                       low.rm_startblock = 0;
+       }
+}
+
 static int
 fsmap_f(
        int                     argc,
@@ -111,14 +240,18 @@ fsmap_f(
        int                     c;
        xfs_fsblock_t           start_fsb = 0;
        xfs_fsblock_t           end_fsb = NULLFSBLOCK;
+       bool                    isrt = false;
 
        if (!xfs_has_rmapbt(mp)) {
                dbprintf(_("Filesystem does not support reverse mapping btree.\n"));
                return 0;
        }
 
-       while ((c = getopt(argc, argv, "")) != EOF) {
+       while ((c = getopt(argc, argv, "r")) != EOF) {
                switch (c) {
+               case 'r':
+                       isrt = true;
+                       break;
                default:
                        dbprintf(_("Bad option for fsmap command.\n"));
                        return 0;
@@ -141,14 +274,23 @@ fsmap_f(
                }
        }
 
-       fsmap(start_fsb, end_fsb);
+       if (argc > optind + 2) {
+               exitcode = 1;
+               dbprintf(_("Too many arguments to fsmap.\n"));
+               return 0;
+       }
+
+       if (isrt)
+               fsmap_rt(start_fsb, end_fsb);
+       else
+               fsmap(start_fsb, end_fsb);
 
        return 0;
 }
 
 static const cmdinfo_t fsmap_cmd =
-       { "fsmap", NULL, fsmap_f, 0, 2, 0,
-         N_("[start_fsb] [end_fsb]"),
+       { "fsmap", NULL, fsmap_f, 0, -1, 0,
+         N_("[-r] [start_fsb] [end_fsb]"),
          N_("display reverse mapping(s)"), NULL };
 
 void
index ad7427f57c6dd953baa218d88c4ee6fd1963c64e..6f25a3c7f4be4850e5574e848c58dea4eccaee62 100644 (file)
 #define xfs_rtginode_name              libxfs_rtginode_name
 #define xfs_rtsummary_create           libxfs_rtsummary_create
 
+#define xfs_rtginode_irele             libxfs_rtginode_irele
 #define xfs_rtginode_load              libxfs_rtginode_load
 #define xfs_rtginode_load_parent       libxfs_rtginode_load_parent
 #define xfs_rtgroup_alloc              libxfs_rtgroup_alloc
 #define xfs_rtfree_extent              libxfs_rtfree_extent
 #define xfs_rtfree_blocks              libxfs_rtfree_blocks
 #define xfs_update_rtsb                        libxfs_update_rtsb
+#define xfs_rtgroup_put                        libxfs_rtgroup_put
 #define xfs_rtrmapbt_droot_maxrecs     libxfs_rtrmapbt_droot_maxrecs
 #define xfs_rtrmapbt_maxlevels_ondisk  libxfs_rtrmapbt_maxlevels_ondisk
+#define xfs_rtrmapbt_init_cursor       libxfs_rtrmapbt_init_cursor
 #define xfs_rtrmapbt_maxrecs           libxfs_rtrmapbt_maxrecs
 
 #define xfs_sb_from_disk               libxfs_sb_from_disk