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 | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index ca8e231c0fd..e171755a6f0 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -106,6 +106,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 b4ebcd56d57..1184392ff47 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -165,6 +165,28 @@ is_meta_ino( return reason != NULL; } +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_flags2 & cpu_to_be64(XFS_DIFLAG2_METADIR))) + 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 @@ -256,6 +278,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 (is_meta_ino(mp, ino, dip, lino, &junkreason)) { /* * Directories that are not in the metadir tree should @@ -718,6 +746,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 (is_meta_ino(mp, ino, dip, ent_ino, &clearreason)) { /* * Directories that are not in the metadir tree should