From 9e3bc76eb66270044a2cf4a3be330fc3a84da41d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 19 Dec 2024 19:49:38 -0800 Subject: [PATCH] xfs_repair: support repairing zoned file systems Note really much to do here. Mostly ignore the validation and regeneration of the bitmap and summary inodes. Eventually this could grow a bit of validation of the hardware zone state. Signed-off-by: Christoph Hellwig --- repair/dinode.c | 4 +++- repair/phase5.c | 13 +++++++++++++ repair/phase6.c | 6 ++++-- repair/rt.c | 2 ++ repair/rtrmap_repair.c | 33 +++++++++++++++++++++++++++++++++ repair/xfs_repair.c | 9 ++++++--- 6 files changed, 61 insertions(+), 6 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 8696a8380..7bdd3dcf1 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -3585,7 +3585,9 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), validate_extsize(mp, dino, lino, dirty); - if (dino->di_version >= 3) + if (dino->di_version >= 3 && + (!xfs_has_zoned(mp) || + dino->di_metatype != cpu_to_be16(XFS_METAFILE_RTRMAP))) validate_cowextsize(mp, dino, lino, dirty); /* nsec fields cannot be larger than 1 billion */ diff --git a/repair/phase5.c b/repair/phase5.c index 4cf28d8ae..e350b411c 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -630,6 +630,19 @@ void check_rtmetadata( struct xfs_mount *mp) { + if (xfs_has_zoned(mp)) { + /* + * Here we could/should verify the zone state a bit when we are + * on actual zoned devices: + * - compare hw write pointer to last written + * - compare zone state to last written + * + * Note much we can do when running in zoned mode on a + * conventional device. + */ + return; + } + generate_rtinfo(mp); check_rtbitmap(mp); check_rtsummary(mp); diff --git a/repair/phase6.c b/repair/phase6.c index dbc090a54..a7187e84d 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -3460,8 +3460,10 @@ _(" - resetting contents of realtime bitmap and summary inodes\n")); return; while ((rtg = xfs_rtgroup_next(mp, rtg))) { - ensure_rtgroup_bitmap(rtg); - ensure_rtgroup_summary(rtg); + if (!xfs_has_zoned(mp)) { + ensure_rtgroup_bitmap(rtg); + ensure_rtgroup_summary(rtg); + } ensure_rtgroup_rmapbt(rtg, est_fdblocks); ensure_rtgroup_refcountbt(rtg, est_fdblocks); } diff --git a/repair/rt.c b/repair/rt.c index e0a4943ee..a2478fb63 100644 --- a/repair/rt.c +++ b/repair/rt.c @@ -222,6 +222,8 @@ check_rtfile_contents( xfs_fileoff_t bno = 0; int error; + ASSERT(!xfs_has_zoned(mp)); + if (!ip) { do_warn(_("unable to open %s file\n"), filename); return; diff --git a/repair/rtrmap_repair.c b/repair/rtrmap_repair.c index 2b07e8943..955db1738 100644 --- a/repair/rtrmap_repair.c +++ b/repair/rtrmap_repair.c @@ -141,6 +141,37 @@ xrep_rtrmap_btree_load( return error; } +static void +rtgroup_update_counters( + struct xfs_rtgroup *rtg) +{ + struct xfs_inode *rmapip = rtg->rtg_inodes[XFS_RTGI_RMAP]; + struct xfs_mount *mp = rtg_mount(rtg); + uint64_t end = + xfs_rtbxlen_to_blen(mp, rtg->rtg_extents); + xfs_agblock_t gbno = 0; + uint64_t used = 0; + + do { + int bstate; + xfs_extlen_t blen; + + bstate = get_bmap_ext(rtg_rgno(rtg), gbno, end, &blen, true); + switch (bstate) { + case XR_E_INUSE: + case XR_E_INUSE_FS: + used += blen; + break; + default: + break; + } + + gbno += blen; + } while (gbno < end); + + rmapip->i_used_blocks = used; +} + /* Update the inode counters. */ STATIC int xrep_rtrmap_reset_counters( @@ -153,6 +184,8 @@ xrep_rtrmap_reset_counters( * generated. */ sc->ip->i_nblocks = rr->new_fork_info.ifake.if_blocks; + if (xfs_has_zoned(sc->mp)) + rtgroup_update_counters(rr->rtg); libxfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE); /* Quotas don't exist so we're done. */ diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index eeaaf6434..7bf75c09b 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -1388,16 +1388,19 @@ main(int argc, char **argv) * Done with the block usage maps, toss them. Realtime metadata aren't * rebuilt until phase 6, so we have to keep them around. */ - if (mp->m_sb.sb_rblocks == 0) + if (mp->m_sb.sb_rblocks == 0) { rmaps_free(mp); - free_bmaps(mp); + free_bmaps(mp); + } if (!bad_ino_btree) { phase6(mp); phase_end(mp, 6); - if (mp->m_sb.sb_rblocks != 0) + if (mp->m_sb.sb_rblocks != 0) { rmaps_free(mp); + free_bmaps(mp); + } free_rtgroup_inodes(); phase7(mp, phase2_threads); -- 2.50.1