From: Darrick J. Wong <djwong@xxxxxxxxxx> Extend the 'fsmap' debugger command to support querying the realtime rmap btree via a new -r argument. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- db/fsmap.c | 149 +++++++++++++++++++++++++++++++++++++++++++++- libxfs/libxfs_api_defs.h | 3 + 2 files changed, 148 insertions(+), 4 deletions(-) diff --git a/db/fsmap.c b/db/fsmap.c index a9259c4632185b..ddbe4e6a3dfcfa 100644 --- a/db/fsmap.c +++ b/db/fsmap.c @@ -102,6 +102,134 @@ 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_group->xg_gno, 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_mount(rtg); + 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_rgno(rtg)); + 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_rgno(rtg), error); + goto out_rele_dp; + } + + bt_cur = libxfs_rtrmapbt_init_cursor(tp, rtg); + 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 = NULL; + 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; + while ((rtg = xfs_rtgroup_next_range(mp, rtg, start_rg, end_rg))) { + if (rtg_rgno(rtg) == 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_rgno(rtg) == start_rg) + low.rm_startblock = 0; + } +} + static int fsmap_f( int argc, @@ -111,14 +239,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 +273,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 diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index cf88656946ab1b..3e521cd0c76063 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -295,6 +295,7 @@ #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 @@ -310,8 +311,10 @@ #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