[PATCH 13/22] xfs_repair: find and mark the rtrefcountbt inode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Darrick J. Wong <djwong@xxxxxxxxxx>

Make sure that we find the realtime refcountbt inode and mark it
appropriately, just in case we find a rogue inode claiming to
be an rtrefcount, or just plain garbage in the superblock field.

Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx>
---
 repair/dino_chunks.c |   11 +++++++++++
 repair/dinode.c      |   49 +++++++++++++++++++++++++++++++++++++++++--------
 repair/dir2.c        |    5 +++++
 repair/incore.h      |    1 +
 repair/rmap.c        |    5 ++++-
 repair/rmap.h        |    2 +-
 repair/scan.c        |    8 ++++----
 7 files changed, 67 insertions(+), 14 deletions(-)


diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c
index 8c5387cdf4ea52..250985ec264ead 100644
--- a/repair/dino_chunks.c
+++ b/repair/dino_chunks.c
@@ -1036,6 +1036,17 @@ process_inode_chunk(
 	_("would clear rtgroup rmap inode %" PRIu64 "\n"),
 						ino);
 				}
+			} else if (is_rtrefcount_inode(ino)) {
+				refcount_avoid_check(mp);
+				if (!no_modify)  {
+					do_warn(
+	_("cleared rtgroup refcount inode %" PRIu64 "\n"),
+						ino);
+				} else  {
+					do_warn(
+	_("would clear rtgroup refcount inode %" PRIu64 "\n"),
+						ino);
+				}
 			} else if (!no_modify)  {
 				do_warn(_("cleared inode %" PRIu64 "\n"),
 					ino);
diff --git a/repair/dinode.c b/repair/dinode.c
index ac5db8b0ea4392..3260df94511ed2 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -181,6 +181,9 @@ clear_dinode(
 
 	if (is_rtrmap_inode(ino_num))
 		rmap_avoid_check(mp);
+
+	if (is_rtrefcount_inode(ino_num))
+		refcount_avoid_check(mp);
 }
 
 /*
@@ -1139,14 +1142,27 @@ _("rtrefcount inode %" PRIu64 " not flagged as metadata\n"),
 		return 1;
 	}
 
-	if (!is_rtrefcount_inode(lino)) {
-		do_warn(
-_("could not associate refcount inode %" PRIu64 " with any rtgroup\n"),
-			lino);
-		return 1;
-	}
-
+	/*
+	 * If this rtrefcount file claims to be from an rtgroup that actually
+	 * exists, check that inode discovery actually found it.  Note that
+	 * we can have stray rtrefcount files from failed growfsrt operations.
+	 */
 	priv.rgno = metafile_rgnumber(dip);
+	if (priv.rgno < mp->m_sb.sb_rgcount) {
+		if (type != XR_INO_RTREFC) {
+			do_warn(
+_("rtrefcount inode %" PRIu64 " was not found in the metadata directory tree\n"),
+				lino);
+			return 1;
+		}
+
+		if (!is_rtrefcount_inode(lino)) {
+			do_warn(
+_("could not associate refcount inode %" PRIu64 " with any rtgroup\n"),
+				lino);
+			return 1;
+		}
+	}
 
 	dib = (struct xfs_rtrefcount_root *)XFS_DFORK_PTR(dip, XFS_DATA_FORK);
 	*tot = 0;
@@ -1179,7 +1195,7 @@ _("computed size of rtrefcountbt root (%zu bytes) is greater than space in "
 		error = process_rtrefc_reclist(mp, rp, numrecs,
 				&priv, "rtrefcountbt root");
 		if (error) {
-			refcount_avoid_check();
+			refcount_avoid_check(mp);
 			return 1;
 		}
 		return 0;
@@ -2143,6 +2159,9 @@ process_check_metadata_inodes(
 	if (is_rtrmap_inode(lino))
 		return process_check_rt_inode(mp, dinoc, lino, type, dirty,
 				XR_INO_RTRMAP, _("realtime rmap btree"));
+	if (is_rtrefcount_inode(lino))
+		return process_check_rt_inode(mp, dinoc, lino, type, dirty,
+				XR_INO_RTREFC, _("realtime refcount btree"));
 	return 0;
 }
 
@@ -2253,6 +2272,18 @@ _("found inode %" PRIu64 " claiming to be a rtrmapbt file, but rmapbt is disable
 		}
 		break;
 
+	case XR_INO_RTREFC:
+		/*
+		 * if we have no refcountbt, any inode claiming
+		 * to be a real-time file is bogus
+		 */
+		if (!xfs_has_reflink(mp)) {
+			do_warn(
+_("found inode %" PRIu64 " claiming to be a rtrefcountbt file, but reflink is disabled\n"), lino);
+			return 1;
+		}
+		break;
+
 	default:
 		break;
 	}
@@ -3453,6 +3484,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
 			type = XR_INO_PQUOTA;
 		else if (is_rtrmap_inode(lino))
 			type = XR_INO_RTRMAP;
+		else if (is_rtrefcount_inode(lino))
+			type = XR_INO_RTREFC;
 		else
 			type = XR_INO_DATA;
 		break;
diff --git a/repair/dir2.c b/repair/dir2.c
index af00b2d8d6c852..a80160afaea5cf 100644
--- a/repair/dir2.c
+++ b/repair/dir2.c
@@ -282,6 +282,9 @@ process_sf_dir2(
 		} else if (is_rtrmap_inode(lino)) {
 			junkit = 1;
 			junkreason = _("realtime rmap");
+		} else if (is_rtrefcount_inode(lino)) {
+			junkit = 1;
+			junkreason = _("realtime refcount");
 		} else if ((irec_p = find_inode_rec(mp,
 					XFS_INO_TO_AGNO(mp, lino),
 					XFS_INO_TO_AGINO(mp, lino))) != NULL) {
@@ -761,6 +764,8 @@ process_dir2_data(
 			clearreason = _("metadata directory root");
 		} else if (is_rtrmap_inode(ent_ino)) {
 			clearreason = _("realtime rmap");
+		} else if (is_rtrefcount_inode(ent_ino)) {
+			clearreason = _("realtime refcount");
 		} else {
 			irec_p = find_inode_rec(mp,
 						XFS_INO_TO_AGNO(mp, ent_ino),
diff --git a/repair/incore.h b/repair/incore.h
index 4add12615e0a04..57019148f588c3 100644
--- a/repair/incore.h
+++ b/repair/incore.h
@@ -242,6 +242,7 @@ int		count_bcnt_extents(xfs_agnumber_t);
 #define XR_INO_GQUOTA	13		/* group quota inode */
 #define XR_INO_PQUOTA	14		/* project quota inode */
 #define XR_INO_RTRMAP	15		/* realtime rmap */
+#define XR_INO_RTREFC	16		/* realtime refcount */
 
 /* inode allocation tree */
 
diff --git a/repair/rmap.c b/repair/rmap.c
index 85a65048db9afc..e39c74cc7b44f7 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -1699,8 +1699,11 @@ init_refcount_cursor(
  * Disable the refcount btree check.
  */
 void
-refcount_avoid_check(void)
+refcount_avoid_check(
+	struct xfs_mount	*mp)
 {
+	if (xfs_has_rtgroups(mp))
+		mark_rtgroup_inodes_bad(mp, XFS_RTGI_REFCOUNT);
 	refcbt_suspect = true;
 }
 
diff --git a/repair/rmap.h b/repair/rmap.h
index 23859bf6c2ad42..c0984d97322861 100644
--- a/repair/rmap.h
+++ b/repair/rmap.h
@@ -41,7 +41,7 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec,
 extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t);
 uint64_t refcount_record_count(struct xfs_mount *mp, xfs_agnumber_t agno);
 extern int init_refcount_cursor(xfs_agnumber_t, struct xfs_slab_cursor **);
-extern void refcount_avoid_check(void);
+extern void refcount_avoid_check(struct xfs_mount *mp);
 void check_refcounts(struct xfs_mount *mp, xfs_agnumber_t agno);
 
 extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *,
diff --git a/repair/scan.c b/repair/scan.c
index 21fa9018800c77..86565ebb9f2faf 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -1980,7 +1980,7 @@ _("extent (%u/%u) len %u claimed, state is %d\n"),
 	libxfs_perag_put(pag);
 out:
 	if (suspect)
-		refcount_avoid_check();
+		refcount_avoid_check(mp);
 	return;
 }
 
@@ -2285,7 +2285,7 @@ _("%s btree block claimed (state %d), agno %d, agbno %d, suspect %d\n"),
 	}
 out:
 	if (suspect) {
-		refcount_avoid_check();
+		refcount_avoid_check(mp);
 		return 1;
 	}
 
@@ -3148,7 +3148,7 @@ validate_agf(
 		if (levels == 0 || levels > mp->m_refc_maxlevels) {
 			do_warn(_("bad levels %u for refcountbt root, agno %d\n"),
 				levels, agno);
-			refcount_avoid_check();
+			refcount_avoid_check(mp);
 		}
 
 		bno = be32_to_cpu(agf->agf_refcount_root);
@@ -3166,7 +3166,7 @@ validate_agf(
 		} else {
 			do_warn(_("bad agbno %u for refcntbt root, agno %d\n"),
 				bno, agno);
-			refcount_avoid_check();
+			refcount_avoid_check(mp);
 		}
 	}
 





[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux