[PATCH 14/50] xfs_repair: refactor phase4

Darrick J. Wong
2024-12-07T00:08:34Z

From: Christoph Hellwig <hch@lst.de>

Split out helpers to process all duplicate extents in an AG and the RT
duplicate extents.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
repair/phase4.c | 210 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 114 insertions(+), 96 deletions(-)

diff --git a/repair/phase4.c b/repair/phase4.c
index 40db36f1f93020..036a4ed0e54445 100644
--- a/repair/phase4.c
+++ b/repair/phase4.c
@@ -225,20 +225,122 @@ process_rmap_data(
destroy_work_queue(&wq);
}

+static void
+process_dup_rt_extents(
+ struct xfs_mount *mp)
+{
+ xfs_rtxnum_t rt_start = 0;
+ xfs_rtxlen_t rt_len = 0;
+ xfs_rtxnum_t rtx;
+
+ for (rtx = 0; rtx < mp->m_sb.sb_rextents; rtx++) {
+ int state;
+
+ state = get_rtbmap(rtx);
+ switch (state) {
+ case XR_E_BAD_STATE:
+ default:
+ do_warn(
+ _("unknown rt extent state %d, extent %" PRIu64 "\n"),
+ state, rtx);
+ fallthrough;
+ case XR_E_METADATA:
+ case XR_E_UNKNOWN:
+ case XR_E_FREE1:
+ case XR_E_FREE:
+ case XR_E_INUSE:
+ case XR_E_INUSE_FS:
+ case XR_E_INO:
+ case XR_E_FS_MAP:
+ if (rt_start == 0)
+ continue;
+ /*
+ * Add extent and reset extent state.
+ */
+ add_rt_dup_extent(rt_start, rt_len);
+ rt_start = 0;
+ rt_len = 0;
+ break;
+ case XR_E_MULT:
+ switch (rt_start) {
+ case 0:
+ rt_start = rtx;
+ rt_len = 1;
+ break;
+ case XFS_MAX_BMBT_EXTLEN:
+ /*
+ * Large extent case.
+ */
+ add_rt_dup_extent(rt_start, rt_len);
+ rt_start = rtx;
+ rt_len = 1;
+ break;
+ default:
+ rt_len++;
+ break;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Catch the tail case, extent hitting the end of the RTG.
+ */
+ if (rt_start != 0)
+ add_rt_dup_extent(rt_start, rt_len);
+}
+
+/*
+ * Set up duplicate extent list for an AG or RTG.
+ */
+static void
+process_dup_extents(
+ xfs_agnumber_t agno,
+ xfs_agblock_t agbno,
+ xfs_agblock_t ag_end)
+{
+ do {
+ int bstate;
+ xfs_extlen_t blen;
+
+ bstate = get_bmap_ext(agno, agbno, ag_end, &blen);
+ switch (bstate) {
+ case XR_E_FREE1:
+ if (no_modify)
+ do_warn(
+_("free space (%u,%u-%u) only seen by one free space btree\n"),
+ agno, agbno, agbno + blen - 1);
+ break;
+ case XR_E_METADATA:
+ case XR_E_UNKNOWN:
+ case XR_E_FREE:
+ case XR_E_INUSE:
+ case XR_E_INUSE_FS:
+ case XR_E_INO:
+ case XR_E_FS_MAP:
+ break;
+ case XR_E_MULT:
+ add_dup_extent(agno, agbno, blen);
+ break;
+ case XR_E_BAD_STATE:
+ default:
+ do_warn(
+_("unknown block state, ag %d, blocks %u-%u\n"),
+ agno, agbno, agbno + blen - 1);
+ break;
+ }
+
+ agbno += blen;
+ } while (agbno < ag_end);
+}
+
void
phase4(xfs_mount_t *mp)
{
ino_tree_node_t *irec;
- xfs_rtxnum_t rtx;
- xfs_rtxnum_t rt_start;
- xfs_rtxlen_t rt_len;
xfs_agnumber_t i;
- xfs_agblock_t j;
- xfs_agblock_t ag_end;
- xfs_extlen_t blen;
int ag_hdr_len = 4 * mp->m_sb.sb_sectsize;
int ag_hdr_block;
- int bstate;

if (rmap_needs_work(mp))
collect_rmaps = true;
@@ -281,102 +383,19 @@ phase4(xfs_mount_t *mp)
}

for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+ xfs_agblock_t ag_end;
+
ag_end = (i < mp->m_sb.sb_agcount - 1) ? mp->m_sb.sb_agblocks :
mp->m_sb.sb_dblocks -
(xfs_rfsblock_t) mp->m_sb.sb_agblocks * i;

- /*
- * set up duplicate extent list for this ag
- */
- for (j = ag_hdr_block; j < ag_end; j += blen) {
- bstate = get_bmap_ext(i, j, ag_end, &blen);
- switch (bstate) {
- case XR_E_FREE1:
- if (no_modify)
- do_warn(
- _("free space (%u,%u-%u) only seen by one free space btree\n"),
- i, j, j + blen - 1);
- break;
- case XR_E_BAD_STATE:
- default:
- do_warn(
- _("unknown block state, ag %d, blocks %u-%u\n"),
- i, j, j + blen - 1);
- fallthrough;
- case XR_E_METADATA:
- case XR_E_UNKNOWN:
- case XR_E_FREE:
- case XR_E_INUSE:
- case XR_E_INUSE_FS:
- case XR_E_INO:
- case XR_E_FS_MAP:
- break;
- case XR_E_MULT:
- add_dup_extent(i, j, blen);
- break;
- }
- }
+ process_dup_extents(i, ag_hdr_block, ag_end);

PROG_RPT_INC(prog_rpt_done[i], 1);
}
print_final_rpt();

- /*
- * initialize realtime bitmap
- */
- rt_start = 0;
- rt_len = 0;
-
- for (rtx = 0; rtx < mp->m_sb.sb_rextents; rtx++) {
- bstate = get_rtbmap(rtx);
- switch (bstate) {
- case XR_E_BAD_STATE:
- default:
- do_warn(
- _("unknown rt extent state, extent %" PRIu64 "\n"),
- rtx);
- fallthrough;
- case XR_E_METADATA:
- case XR_E_UNKNOWN:
- case XR_E_FREE1:
- case XR_E_FREE:
- case XR_E_INUSE:
- case XR_E_INUSE_FS:
- case XR_E_INO:
- case XR_E_FS_MAP:
- if (rt_start == 0)
- continue;
- else {
- /*
- * add extent and reset extent state
- */
- add_rt_dup_extent(rt_start, rt_len);
- rt_start = 0;
- rt_len = 0;
- }
- break;
- case XR_E_MULT:
- if (rt_start == 0) {
- rt_start = rtx;
- rt_len = 1;
- } else if (rt_len == XFS_MAX_BMBT_EXTLEN) {
- /*
- * large extent case
- */
- add_rt_dup_extent(rt_start, rt_len);
- rt_start = rtx;
- rt_len = 1;
- } else
- rt_len++;
- break;
- }
- }
-
- /*
- * catch tail-case, extent hitting the end of the ag
- */
- if (rt_start != 0)
- add_rt_dup_extent(rt_start, rt_len);
+ process_dup_rt_extents(mp);

/*
* initialize bitmaps for all AGs
@@ -410,8 +429,7 @@ phase4(xfs_mount_t *mp)
/*
* free up memory used to track trealtime duplicate extents
*/
- if (rt_start != 0)
- free_rt_dup_extent_tree(mp);
+ free_rt_dup_extent_tree(mp);

/*
* ensure consistency of quota inode pointers in superblock,