diff mbox series

[4/5] xfs: support inode btree blockcounts in online repair

Message ID 159901537765.547164.7777551130535148618.stgit@magnolia
State Accepted
Headers show
Series xfs: add inode btree blocks counters to the AGI header | expand

Commit Message

Darrick J. Wong Sept. 2, 2020, 2:56 a.m. UTC
From: Darrick J. Wong <darrick.wong@oracle.com>

Add the necessary bits to the online repair code to support logging the
inode btree counters when rebuilding the btrees, and to support fixing
the counters when rebuilding the AGI.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_ialloc_btree.c |   16 +++++++++++++---
 fs/xfs/scrub/agheader_repair.c   |   24 ++++++++++++++++++++++++
 2 files changed, 37 insertions(+), 3 deletions(-)

Comments

Brian Foster Sept. 2, 2020, 1:23 p.m. UTC | #1
On Tue, Sep 01, 2020 at 07:56:17PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Add the necessary bits to the online repair code to support logging the
> inode btree counters when rebuilding the btrees, and to support fixing
> the counters when rebuilding the AGI.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_ialloc_btree.c |   16 +++++++++++++---
>  fs/xfs/scrub/agheader_repair.c   |   24 ++++++++++++++++++++++++
>  2 files changed, 37 insertions(+), 3 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
> index 1df04e48bd87..219f57f4b5a7 100644
> --- a/fs/xfs/libxfs/xfs_ialloc_btree.c
> +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
> @@ -504,19 +504,29 @@ xfs_inobt_commit_staged_btree(
>  {
>  	struct xfs_agi		*agi = agbp->b_addr;
>  	struct xbtree_afakeroot	*afake = cur->bc_ag.afake;
> +	int			fields;
>  
>  	ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
>  
>  	if (cur->bc_btnum == XFS_BTNUM_INO) {
> +		fields = XFS_AGI_ROOT | XFS_AGI_LEVEL;
>  		agi->agi_root = cpu_to_be32(afake->af_root);
>  		agi->agi_level = cpu_to_be32(afake->af_levels);
> -		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL);
> +		if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) {
> +			agi->agi_iblocks = cpu_to_be32(afake->af_blocks);
> +			fields |= XFS_AGI_IBLOCKS;
> +		}
> +		xfs_ialloc_log_agi(tp, agbp, fields);
>  		xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_inobt_ops);
>  	} else {
> +		fields = XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL;
>  		agi->agi_free_root = cpu_to_be32(afake->af_root);
>  		agi->agi_free_level = cpu_to_be32(afake->af_levels);
> -		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREE_ROOT |
> -					     XFS_AGI_FREE_LEVEL);
> +		if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) {
> +			agi->agi_fblocks = cpu_to_be32(afake->af_blocks);
> +			fields |= XFS_AGI_IBLOCKS;
> +		}
> +		xfs_ialloc_log_agi(tp, agbp, fields);
>  		xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_finobt_ops);
>  	}
>  }
> diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c
> index bca2ab1d4be9..401f71579ce6 100644
> --- a/fs/xfs/scrub/agheader_repair.c
> +++ b/fs/xfs/scrub/agheader_repair.c
> @@ -810,10 +810,34 @@ xrep_agi_calc_from_btrees(
>  	error = xfs_ialloc_count_inodes(cur, &count, &freecount);
>  	if (error)
>  		goto err;
> +	if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
> +		xfs_agblock_t	blocks;
> +
> +		error = xfs_btree_count_blocks(cur, &blocks);
> +		if (error)
> +			goto err;
> +		agi->agi_iblocks = cpu_to_be32(blocks);
> +	}
>  	xfs_btree_del_cursor(cur, error);
>  
>  	agi->agi_count = cpu_to_be32(count);
>  	agi->agi_freecount = cpu_to_be32(freecount);
> +
> +	if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
> +	    xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
> +		xfs_agblock_t	blocks;
> +
> +		cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp, sc->sa.agno,
> +				XFS_BTNUM_FINO);
> +		if (error)
> +			goto err;
> +		error = xfs_btree_count_blocks(cur, &blocks);
> +		if (error)
> +			goto err;
> +		xfs_btree_del_cursor(cur, error);
> +		agi->agi_fblocks = cpu_to_be32(blocks);
> +	}
> +
>  	return 0;
>  err:
>  	xfs_btree_del_cursor(cur, error);
>
diff mbox series

Patch

diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index 1df04e48bd87..219f57f4b5a7 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -504,19 +504,29 @@  xfs_inobt_commit_staged_btree(
 {
 	struct xfs_agi		*agi = agbp->b_addr;
 	struct xbtree_afakeroot	*afake = cur->bc_ag.afake;
+	int			fields;
 
 	ASSERT(cur->bc_flags & XFS_BTREE_STAGING);
 
 	if (cur->bc_btnum == XFS_BTNUM_INO) {
+		fields = XFS_AGI_ROOT | XFS_AGI_LEVEL;
 		agi->agi_root = cpu_to_be32(afake->af_root);
 		agi->agi_level = cpu_to_be32(afake->af_levels);
-		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL);
+		if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) {
+			agi->agi_iblocks = cpu_to_be32(afake->af_blocks);
+			fields |= XFS_AGI_IBLOCKS;
+		}
+		xfs_ialloc_log_agi(tp, agbp, fields);
 		xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_inobt_ops);
 	} else {
+		fields = XFS_AGI_FREE_ROOT | XFS_AGI_FREE_LEVEL;
 		agi->agi_free_root = cpu_to_be32(afake->af_root);
 		agi->agi_free_level = cpu_to_be32(afake->af_levels);
-		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREE_ROOT |
-					     XFS_AGI_FREE_LEVEL);
+		if (xfs_sb_version_hasinobtcounts(&cur->bc_mp->m_sb)) {
+			agi->agi_fblocks = cpu_to_be32(afake->af_blocks);
+			fields |= XFS_AGI_IBLOCKS;
+		}
+		xfs_ialloc_log_agi(tp, agbp, fields);
 		xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_finobt_ops);
 	}
 }
diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c
index bca2ab1d4be9..401f71579ce6 100644
--- a/fs/xfs/scrub/agheader_repair.c
+++ b/fs/xfs/scrub/agheader_repair.c
@@ -810,10 +810,34 @@  xrep_agi_calc_from_btrees(
 	error = xfs_ialloc_count_inodes(cur, &count, &freecount);
 	if (error)
 		goto err;
+	if (xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+		xfs_agblock_t	blocks;
+
+		error = xfs_btree_count_blocks(cur, &blocks);
+		if (error)
+			goto err;
+		agi->agi_iblocks = cpu_to_be32(blocks);
+	}
 	xfs_btree_del_cursor(cur, error);
 
 	agi->agi_count = cpu_to_be32(count);
 	agi->agi_freecount = cpu_to_be32(freecount);
+
+	if (xfs_sb_version_hasfinobt(&mp->m_sb) &&
+	    xfs_sb_version_hasinobtcounts(&mp->m_sb)) {
+		xfs_agblock_t	blocks;
+
+		cur = xfs_inobt_init_cursor(mp, sc->tp, agi_bp, sc->sa.agno,
+				XFS_BTNUM_FINO);
+		if (error)
+			goto err;
+		error = xfs_btree_count_blocks(cur, &blocks);
+		if (error)
+			goto err;
+		xfs_btree_del_cursor(cur, error);
+		agi->agi_fblocks = cpu_to_be32(blocks);
+	}
+
 	return 0;
 err:
 	xfs_btree_del_cursor(cur, error);