[PATCH 22/41] xfs_repair: dont check metadata directory dirent inumbers

Darrick J. Wong
2024-12-06T23:45:23Z

From: Darrick J. Wong <djwong@kernel.org>

Phase 6 always rebuilds the entire metadata directory tree, and repair
quietly ignores all the DIFLAG2_METADATA directory inodes that it finds.
As a result, none of the metadata directories are marked inuse in the
incore data. Therefore, the is_inode_free checks are not valid for
anything we find in a metadata directory.

Therefore, avoid checking is_inode_free when scanning metadata directory
dirents.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
libxfs/libxfs_api_defs.h | 1 +
repair/dir2.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+)

diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h
index dd163709fe07df..d2611d7a764259 100644
--- a/libxfs/libxfs_api_defs.h
+++ b/libxfs/libxfs_api_defs.h
@@ -121,6 +121,7 @@
#define xfs_dinode_calc_crc libxfs_dinode_calc_crc
#define xfs_dinode_good_version libxfs_dinode_good_version
#define xfs_dinode_verify libxfs_dinode_verify
+#define xfs_dinode_verify_metadir libxfs_dinode_verify_metadir

#define xfs_dir2_data_bestfree_p libxfs_dir2_data_bestfree_p
#define xfs_dir2_data_entry_tag_p libxfs_dir2_data_entry_tag_p
diff --git a/repair/dir2.c b/repair/dir2.c
index bfeaddd07d2058..dab6523f676a34 100644
--- a/repair/dir2.c
+++ b/repair/dir2.c
@@ -136,6 +136,29 @@ process_sf_dir2_fixoff(
}
}

+static inline bool
+is_metadata_directory(
+ struct xfs_mount *mp,
+ struct xfs_dinode *dip)
+{
+ xfs_failaddr_t fa;
+ uint16_t mode;
+ uint16_t flags;
+ uint64_t flags2;
+
+ if (!xfs_has_metadir(mp))
+ return false;
+ if (dip->di_version < 3 ||
+ !(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADATA)))
+ return false;
+
+ mode = be16_to_cpu(dip->di_mode);
+ flags = be16_to_cpu(dip->di_flags);
+ flags2 = be64_to_cpu(dip->di_flags2);
+ fa = libxfs_dinode_verify_metadir(mp, dip, mode, flags, flags2);
+ return fa == NULL;
+}
+
/*
* this routine performs inode discovery and tries to fix things
* in place. available redundancy -- inode data size should match
@@ -227,6 +250,12 @@ process_sf_dir2(
} else if (!libxfs_verify_dir_ino(mp, lino)) {
junkit = 1;
junkreason = _("invalid");
+ } else if (is_metadata_directory(mp, dip)) {
+ /*
+ * Metadata directories are always rebuilt, so don't
+ * bother checking if the child inode is free or not.
+ */
+ junkit = 0;
} else if (lino == mp->m_sb.sb_rbmino) {
junkit = 1;
junkreason = _("realtime bitmap");
@@ -698,6 +727,12 @@ process_dir2_data(
* directory since it's still structurally intact.
*/
clearreason = _("invalid");
+ } else if (is_metadata_directory(mp, dip)) {
+ /*
+ * Metadata directories are always rebuilt, so don't
+ * bother checking if the child inode is free or not.
+ */
+ clearino = 0;
} else if (ent_ino == mp->m_sb.sb_rbmino) {
clearreason = _("realtime bitmap");
} else if (ent_ino == mp->m_sb.sb_rsumino) {