From b1803dc7b63b99140627a94b37337662234438b8 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 20 Nov 2024 16:24:35 -0800 Subject: [PATCH] xfs_repair: find and clobber rtgroup bitmap and summary files On a rtgroups filesystem, if the rtgroups bitmap or summary files are garbage, we need to clear the dinode and update the incore bitmap so that we don't bother to check the old rt freespace metadata. However, we regenerate the entire rt metadata directory tree during phase 6. If the bitmap and summary files are ok, we still want to clear the dinode, but we can still use the incore inode to check the old freespace contents. Split the clear_dinode function into two pieces, one that merely zeroes the inode, and the old clear_dinode now turns off checking. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dino_chunks.c | 23 +++++++++++++++++++++++ repair/dinode.c | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c index 8935cf85..fe106f0b 100644 --- a/repair/dino_chunks.c +++ b/repair/dino_chunks.c @@ -15,6 +15,7 @@ #include "versions.h" #include "prefetch.h" #include "progress.h" +#include "rt.h" /* * validates inode block or chunk, returns # of good inodes @@ -1000,6 +1001,28 @@ next_readbuf: _("would clear realtime summary inode %" PRIu64 "\n"), ino); } + } else if (is_rtbitmap_inode(ino)) { + mark_rtgroup_inodes_bad(mp, XFS_RTGI_BITMAP); + if (!no_modify) { + do_warn( + _("cleared rtgroup bitmap inode %" PRIu64 "\n"), + ino); + } else { + do_warn( + _("would clear rtgroup bitmap inode %" PRIu64 "\n"), + ino); + } + } else if (is_rtsummary_inode(ino)) { + mark_rtgroup_inodes_bad(mp, XFS_RTGI_SUMMARY); + if (!no_modify) { + do_warn( + _("cleared rtgroup summary inode %" PRIu64 "\n"), + ino); + } else { + do_warn( + _("would clear rtgroup summary inode %" PRIu64 "\n"), + ino); + } } else if (!no_modify) { do_warn(_("cleared inode %" PRIu64 "\n"), ino); diff --git a/repair/dinode.c b/repair/dinode.c index 0a9059db..2d341975 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -149,16 +149,36 @@ clear_dinode_unlinked(xfs_mount_t *mp, struct xfs_dinode *dino) * until after the agi unlinked lists are walked in phase 3. */ static void -clear_dinode(xfs_mount_t *mp, struct xfs_dinode *dino, xfs_ino_t ino_num) +zero_dinode( + struct xfs_mount *mp, + struct xfs_dinode *dino, + xfs_ino_t ino_num) { clear_dinode_core(mp, dino, ino_num); clear_dinode_unlinked(mp, dino); /* and clear the forks */ memset(XFS_DFORK_DPTR(dino), 0, XFS_LITINO(mp)); - return; } +/* + * clear the inode core and, if this is a metadata inode, prevent subsequent + * phases from checking the (obviously bad) data in the file. + */ +static void +clear_dinode( + struct xfs_mount *mp, + struct xfs_dinode *dino, + xfs_ino_t ino_num) +{ + zero_dinode(mp, dino, ino_num); + + if (is_rtbitmap_inode(ino_num)) + mark_rtgroup_inodes_bad(mp, XFS_RTGI_BITMAP); + + if (is_rtsummary_inode(ino_num)) + mark_rtgroup_inodes_bad(mp, XFS_RTGI_SUMMARY); +} /* * misc. inode-related utility routines @@ -3069,13 +3089,21 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "), switch (type) { case XR_INO_RTBITMAP: case XR_INO_RTSUM: + /* + * rt bitmap and summary files are always recreated + * when rtgroups are enabled. For older filesystems, + * they exist at fixed locations and cannot be zapped. + */ + if (xfs_has_rtgroups(mp)) + zap_metadata = true; + break; case XR_INO_UQUOTA: case XR_INO_GQUOTA: case XR_INO_PQUOTA: /* - * This inode was recognized as being filesystem - * metadata, so preserve the inode and its contents for - * later checking and repair. + * Quota checking and repair doesn't happen until + * phase7, so preserve quota inodes and their contents + * for later. */ break; default: @@ -3165,7 +3193,7 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "), * file, zero the ondisk inode and the incore state. */ if (check_dups && zap_metadata && !no_modify) { - clear_dinode(mp, dino, lino); + zero_dinode(mp, dino, lino); *dirty += 1; *used = is_free; *isa_dir = 0; -- 2.47.2