diff mbox series

[27/43] xfs_repair: support repairing zoned file systems

Message ID 20250414053629.360672-28-hch@lst.de (mailing list archive)
State New
Headers show
Series [01/43] xfs: generalize the freespace and reserved blocks handling | expand

Commit Message

Christoph Hellwig April 14, 2025, 5:36 a.m. UTC
Note really much to do here.  Mostly ignore the validation and
regeneration of the bitmap and summary inodes.  Eventually this
could grow a bit of validation of the hardware zone state.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 repair/dinode.c        |  4 +++-
 repair/phase5.c        | 13 +++++++++++++
 repair/phase6.c        |  6 ++++--
 repair/rt.c            |  2 ++
 repair/rtrmap_repair.c | 33 +++++++++++++++++++++++++++++++++
 repair/xfs_repair.c    |  9 ++++++---
 6 files changed, 61 insertions(+), 6 deletions(-)

Comments

Darrick J. Wong April 15, 2025, 12:38 a.m. UTC | #1
On Mon, Apr 14, 2025 at 07:36:10AM +0200, Christoph Hellwig wrote:
> Note really much to do here.  Mostly ignore the validation and
> regeneration of the bitmap and summary inodes.  Eventually this
> could grow a bit of validation of the hardware zone state.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

LGTM
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>

--D

> ---
>  repair/dinode.c        |  4 +++-
>  repair/phase5.c        | 13 +++++++++++++
>  repair/phase6.c        |  6 ++++--
>  repair/rt.c            |  2 ++
>  repair/rtrmap_repair.c | 33 +++++++++++++++++++++++++++++++++
>  repair/xfs_repair.c    |  9 ++++++---
>  6 files changed, 61 insertions(+), 6 deletions(-)
> 
> diff --git a/repair/dinode.c b/repair/dinode.c
> index 8696a838087f..7bdd3dcf15c1 100644
> --- a/repair/dinode.c
> +++ b/repair/dinode.c
> @@ -3585,7 +3585,9 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
>  
>  	validate_extsize(mp, dino, lino, dirty);
>  
> -	if (dino->di_version >= 3)
> +	if (dino->di_version >= 3 &&
> +	    (!xfs_has_zoned(mp) ||
> +	     dino->di_metatype != cpu_to_be16(XFS_METAFILE_RTRMAP)))
>  		validate_cowextsize(mp, dino, lino, dirty);
>  
>  	/* nsec fields cannot be larger than 1 billion */
> diff --git a/repair/phase5.c b/repair/phase5.c
> index 4cf28d8ae1a2..e350b411c243 100644
> --- a/repair/phase5.c
> +++ b/repair/phase5.c
> @@ -630,6 +630,19 @@ void
>  check_rtmetadata(
>  	struct xfs_mount	*mp)
>  {
> +	if (xfs_has_zoned(mp)) {
> +		/*
> +		 * Here we could/should verify the zone state a bit when we are
> +		 * on actual zoned devices:
> +		 *	- compare hw write pointer to last written
> +		 *	- compare zone state to last written
> +		 *
> +		 * Note much we can do when running in zoned mode on a
> +		 * conventional device.
> +		 */
> +		return;
> +	}
> +
>  	generate_rtinfo(mp);
>  	check_rtbitmap(mp);
>  	check_rtsummary(mp);
> diff --git a/repair/phase6.c b/repair/phase6.c
> index dbc090a54139..a7187e84daae 100644
> --- a/repair/phase6.c
> +++ b/repair/phase6.c
> @@ -3460,8 +3460,10 @@ _("        - resetting contents of realtime bitmap and summary inodes\n"));
>  		return;
>  
>  	while ((rtg = xfs_rtgroup_next(mp, rtg))) {
> -		ensure_rtgroup_bitmap(rtg);
> -		ensure_rtgroup_summary(rtg);
> +		if (!xfs_has_zoned(mp)) {
> +			ensure_rtgroup_bitmap(rtg);
> +			ensure_rtgroup_summary(rtg);
> +		}
>  		ensure_rtgroup_rmapbt(rtg, est_fdblocks);
>  		ensure_rtgroup_refcountbt(rtg, est_fdblocks);
>  	}
> diff --git a/repair/rt.c b/repair/rt.c
> index e0a4943ee3b7..a2478fb635e3 100644
> --- a/repair/rt.c
> +++ b/repair/rt.c
> @@ -222,6 +222,8 @@ check_rtfile_contents(
>  	xfs_fileoff_t		bno = 0;
>  	int			error;
>  
> +	ASSERT(!xfs_has_zoned(mp));
> +
>  	if (!ip) {
>  		do_warn(_("unable to open %s file\n"), filename);
>  		return;
> diff --git a/repair/rtrmap_repair.c b/repair/rtrmap_repair.c
> index 2b07e8943e59..955db1738fe2 100644
> --- a/repair/rtrmap_repair.c
> +++ b/repair/rtrmap_repair.c
> @@ -141,6 +141,37 @@ xrep_rtrmap_btree_load(
>  	return error;
>  }
>  
> +static void
> +rtgroup_update_counters(
> +	struct xfs_rtgroup	*rtg)
> +{
> +	struct xfs_inode	*rmapip = rtg->rtg_inodes[XFS_RTGI_RMAP];
> +	struct xfs_mount	*mp = rtg_mount(rtg);
> +	uint64_t		end =
> +		xfs_rtbxlen_to_blen(mp, rtg->rtg_extents);
> +	xfs_agblock_t		gbno = 0;
> +	uint64_t		used = 0;
> +
> +	do {
> +		int		bstate;
> +		xfs_extlen_t	blen;
> +
> +		bstate = get_bmap_ext(rtg_rgno(rtg), gbno, end, &blen, true);
> +		switch (bstate) {
> +		case XR_E_INUSE:
> +		case XR_E_INUSE_FS:
> +			used += blen;
> +			break;
> +		default:
> +			break;
> +		}
> +
> +		gbno += blen;
> +	} while (gbno < end);
> +
> +	rmapip->i_used_blocks = used;
> +}
> +
>  /* Update the inode counters. */
>  STATIC int
>  xrep_rtrmap_reset_counters(
> @@ -153,6 +184,8 @@ xrep_rtrmap_reset_counters(
>  	 * generated.
>  	 */
>  	sc->ip->i_nblocks = rr->new_fork_info.ifake.if_blocks;
> +	if (xfs_has_zoned(sc->mp))
> +		rtgroup_update_counters(rr->rtg);
>  	libxfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
>  
>  	/* Quotas don't exist so we're done. */
> diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
> index eeaaf6434689..7bf75c09b945 100644
> --- a/repair/xfs_repair.c
> +++ b/repair/xfs_repair.c
> @@ -1388,16 +1388,19 @@ main(int argc, char **argv)
>  	 * Done with the block usage maps, toss them.  Realtime metadata aren't
>  	 * rebuilt until phase 6, so we have to keep them around.
>  	 */
> -	if (mp->m_sb.sb_rblocks == 0)
> +	if (mp->m_sb.sb_rblocks == 0) {
>  		rmaps_free(mp);
> -	free_bmaps(mp);
> +		free_bmaps(mp);
> +	}
>  
>  	if (!bad_ino_btree)  {
>  		phase6(mp);
>  		phase_end(mp, 6);
>  
> -		if (mp->m_sb.sb_rblocks != 0)
> +		if (mp->m_sb.sb_rblocks != 0) {
>  			rmaps_free(mp);
> +			free_bmaps(mp);
> +		}
>  		free_rtgroup_inodes();
>  
>  		phase7(mp, phase2_threads);
> -- 
> 2.47.2
> 
>
diff mbox series

Patch

diff --git a/repair/dinode.c b/repair/dinode.c
index 8696a838087f..7bdd3dcf15c1 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -3585,7 +3585,9 @@  _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
 
 	validate_extsize(mp, dino, lino, dirty);
 
-	if (dino->di_version >= 3)
+	if (dino->di_version >= 3 &&
+	    (!xfs_has_zoned(mp) ||
+	     dino->di_metatype != cpu_to_be16(XFS_METAFILE_RTRMAP)))
 		validate_cowextsize(mp, dino, lino, dirty);
 
 	/* nsec fields cannot be larger than 1 billion */
diff --git a/repair/phase5.c b/repair/phase5.c
index 4cf28d8ae1a2..e350b411c243 100644
--- a/repair/phase5.c
+++ b/repair/phase5.c
@@ -630,6 +630,19 @@  void
 check_rtmetadata(
 	struct xfs_mount	*mp)
 {
+	if (xfs_has_zoned(mp)) {
+		/*
+		 * Here we could/should verify the zone state a bit when we are
+		 * on actual zoned devices:
+		 *	- compare hw write pointer to last written
+		 *	- compare zone state to last written
+		 *
+		 * Note much we can do when running in zoned mode on a
+		 * conventional device.
+		 */
+		return;
+	}
+
 	generate_rtinfo(mp);
 	check_rtbitmap(mp);
 	check_rtsummary(mp);
diff --git a/repair/phase6.c b/repair/phase6.c
index dbc090a54139..a7187e84daae 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -3460,8 +3460,10 @@  _("        - resetting contents of realtime bitmap and summary inodes\n"));
 		return;
 
 	while ((rtg = xfs_rtgroup_next(mp, rtg))) {
-		ensure_rtgroup_bitmap(rtg);
-		ensure_rtgroup_summary(rtg);
+		if (!xfs_has_zoned(mp)) {
+			ensure_rtgroup_bitmap(rtg);
+			ensure_rtgroup_summary(rtg);
+		}
 		ensure_rtgroup_rmapbt(rtg, est_fdblocks);
 		ensure_rtgroup_refcountbt(rtg, est_fdblocks);
 	}
diff --git a/repair/rt.c b/repair/rt.c
index e0a4943ee3b7..a2478fb635e3 100644
--- a/repair/rt.c
+++ b/repair/rt.c
@@ -222,6 +222,8 @@  check_rtfile_contents(
 	xfs_fileoff_t		bno = 0;
 	int			error;
 
+	ASSERT(!xfs_has_zoned(mp));
+
 	if (!ip) {
 		do_warn(_("unable to open %s file\n"), filename);
 		return;
diff --git a/repair/rtrmap_repair.c b/repair/rtrmap_repair.c
index 2b07e8943e59..955db1738fe2 100644
--- a/repair/rtrmap_repair.c
+++ b/repair/rtrmap_repair.c
@@ -141,6 +141,37 @@  xrep_rtrmap_btree_load(
 	return error;
 }
 
+static void
+rtgroup_update_counters(
+	struct xfs_rtgroup	*rtg)
+{
+	struct xfs_inode	*rmapip = rtg->rtg_inodes[XFS_RTGI_RMAP];
+	struct xfs_mount	*mp = rtg_mount(rtg);
+	uint64_t		end =
+		xfs_rtbxlen_to_blen(mp, rtg->rtg_extents);
+	xfs_agblock_t		gbno = 0;
+	uint64_t		used = 0;
+
+	do {
+		int		bstate;
+		xfs_extlen_t	blen;
+
+		bstate = get_bmap_ext(rtg_rgno(rtg), gbno, end, &blen, true);
+		switch (bstate) {
+		case XR_E_INUSE:
+		case XR_E_INUSE_FS:
+			used += blen;
+			break;
+		default:
+			break;
+		}
+
+		gbno += blen;
+	} while (gbno < end);
+
+	rmapip->i_used_blocks = used;
+}
+
 /* Update the inode counters. */
 STATIC int
 xrep_rtrmap_reset_counters(
@@ -153,6 +184,8 @@  xrep_rtrmap_reset_counters(
 	 * generated.
 	 */
 	sc->ip->i_nblocks = rr->new_fork_info.ifake.if_blocks;
+	if (xfs_has_zoned(sc->mp))
+		rtgroup_update_counters(rr->rtg);
 	libxfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
 
 	/* Quotas don't exist so we're done. */
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index eeaaf6434689..7bf75c09b945 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -1388,16 +1388,19 @@  main(int argc, char **argv)
 	 * Done with the block usage maps, toss them.  Realtime metadata aren't
 	 * rebuilt until phase 6, so we have to keep them around.
 	 */
-	if (mp->m_sb.sb_rblocks == 0)
+	if (mp->m_sb.sb_rblocks == 0) {
 		rmaps_free(mp);
-	free_bmaps(mp);
+		free_bmaps(mp);
+	}
 
 	if (!bad_ino_btree)  {
 		phase6(mp);
 		phase_end(mp, 6);
 
-		if (mp->m_sb.sb_rblocks != 0)
+		if (mp->m_sb.sb_rblocks != 0) {
 			rmaps_free(mp);
+			free_bmaps(mp);
+		}
 		free_rtgroup_inodes();
 
 		phase7(mp, phase2_threads);