From: Darrick J. Wong <djwong@xxxxxxxxxx> Drop the entire metadata directory tree during pass 4 so that we can reinitialize the entire tree in phase 6. The existing metadata files (rtbitmap, rtsummary, quotas) will be reattached to the newly rebuilt directory tree. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- repair/dino_chunks.c | 9 +++++++++ repair/dinode.c | 14 +++++++++++++- repair/phase6.c | 21 +++++++++++---------- repair/scan.c | 2 +- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c index fb2bca66a47..382196cc170 100644 --- a/repair/dino_chunks.c +++ b/repair/dino_chunks.c @@ -952,6 +952,15 @@ process_inode_chunk( clear_inode_isadir(ino_rec, irec_offset); } + /* + * We always reinitialize the rt bitmap and summary inodes if + * the metadata directory feature is enabled. + */ + if (xfs_has_metadir(mp) && !no_modify) { + need_rbmino = -1; + need_rsumino = -1; + } + if (status) { if (mp->m_sb.sb_rootino == ino) { need_root_inode = 1; diff --git a/repair/dinode.c b/repair/dinode.c index 4efc7fe6b8b..5c1f07d5bc1 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -653,7 +653,7 @@ _("illegal state %d in block map %" PRIu64 "\n"), break; } } - if (collect_rmaps) /* && !check_dups */ + if (collect_rmaps && !zap_metadata) /* && !check_dups */ rmap_add_rec(mp, ino, whichfork, &irec); *tot += irec.br_blockcount; } @@ -3077,6 +3077,18 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "), */ *dirty += process_check_inode_nlink_version(dino, lino); + /* + * The entire metadata directory tree will be rebuilt during phase 6. + * Therefore, if we're at the end of phase 4 and this is a metadata + * file, zero the ondisk inode and the incore state. + */ + if (check_dups && zap_metadata && !no_modify) { + clear_dinode(mp, dino, lino); + *dirty += 1; + *used = is_free; + *isa_dir = 0; + } + return retval; clear_bad_out: diff --git a/repair/phase6.c b/repair/phase6.c index c440c2293d1..964342c31d6 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -3638,20 +3638,20 @@ phase6(xfs_mount_t *mp) } } - if (need_metadir_inode) { - if (!no_modify) { + if (!no_modify && xfs_has_metadir(mp)) { + if (need_metadir_inode) do_warn(_("reinitializing metadata root directory\n")); - mk_metadir(mp); - need_metadir_inode = false; - need_metadir_dotdot = 0; - } else { - do_warn(_("would reinitialize metadata root directory\n")); - } + mk_metadir(mp); + need_metadir_inode = false; + need_metadir_dotdot = 0; + } else if (need_metadir_inode) { + do_warn(_("would reinitialize metadata root directory\n")); } if (need_rbmino) { if (!no_modify) { - do_warn(_("reinitializing realtime bitmap inode\n")); + if (need_rbmino > 0) + do_warn(_("reinitializing realtime bitmap inode\n")); mk_rbmino(mp); need_rbmino = 0; } else { @@ -3661,7 +3661,8 @@ phase6(xfs_mount_t *mp) if (need_rsumino) { if (!no_modify) { - do_warn(_("reinitializing realtime summary inode\n")); + if (need_rsumino > 0) + do_warn(_("reinitializing realtime summary inode\n")); mk_rsumino(mp); need_rsumino = 0; } else { diff --git a/repair/scan.c b/repair/scan.c index ef78b4cce50..1f5db1c11ca 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -427,7 +427,7 @@ _("bad state %d, inode %" PRIu64 " bmap block 0x%" PRIx64 "\n"), numrecs = be16_to_cpu(block->bb_numrecs); /* Record BMBT blocks in the reverse-mapping data. */ - if (check_dups && collect_rmaps) { + if (check_dups && collect_rmaps && !zap_metadata) { agno = XFS_FSB_TO_AGNO(mp, bno); pthread_mutex_lock(&ag_locks[agno].lock); rmap_add_bmbt_rec(mp, ino, whichfork, bno);