From: Darrick J. Wong <djwong@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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) {