diff mbox series

[53/58] xfs_repair: drop all the metadata directory files during pass 4

Message ID 170405010653.1809361.5737330654597011552.stgit@frogsfrogsfrogs (mailing list archive)
State Deferred, archived
Headers show
Series [01/58] xfs: don't use the incore struct xfs_sb for offsets into struct xfs_dsb | expand

Commit Message

Darrick J. Wong Dec. 31, 2023, 11:43 p.m. UTC
From: Darrick J. Wong <djwong@kernel.org>

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@kernel.org>
---
 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 mbox series

Patch

diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c
index 7e18991a3d5..a7f9ea70ca7 100644
--- a/repair/dino_chunks.c
+++ b/repair/dino_chunks.c
@@ -950,6 +950,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 52830a85a6f..5c9101fa0b0 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -656,7 +656,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;
 	}
@@ -3084,6 +3084,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 5eeffd5dce9..c7cfc371ac2 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -3798,20 +3798,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  {
@@ -3821,7 +3821,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 c52ace31c2d..3857593b165 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -429,7 +429,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);