xfs: count free space btree blocks when scrubbing pre-lazysbcount fses
authorDarrick J. Wong <djwong@kernel.org>
Tue, 27 Apr 2021 02:06:58 +0000 (19:06 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 29 Apr 2021 14:44:19 +0000 (07:44 -0700)
Since agf_btreeblks didn't exist before the lazysbcount feature, the fs
summary count scrubber needs to walk the free space btrees to determine
the amount of space being used by those btrees.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Gao Xiang <hsiangkao@redhat.com>
fs/xfs/scrub/fscounters.c

index 318b81c0f90d3f3c5860a6a19ec379abe7c95957..f1d1a8c58853ffb22eaf10fb4214be0be1c7eb94 100644 (file)
@@ -13,6 +13,7 @@
 #include "xfs_alloc.h"
 #include "xfs_ialloc.h"
 #include "xfs_health.h"
+#include "xfs_btree.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
 #include "scrub/trace.h"
@@ -143,6 +144,35 @@ xchk_setup_fscounters(
        return xchk_trans_alloc(sc, 0);
 }
 
+/* Count free space btree blocks manually for pre-lazysbcount filesystems. */
+static int
+xchk_fscount_btreeblks(
+       struct xfs_scrub        *sc,
+       struct xchk_fscounters  *fsc,
+       xfs_agnumber_t          agno)
+{
+       xfs_extlen_t            blocks;
+       int                     error;
+
+       error = xchk_ag_init(sc, agno, &sc->sa);
+       if (error)
+               return error;
+
+       error = xfs_btree_count_blocks(sc->sa.bno_cur, &blocks);
+       if (error)
+               goto out_free;
+       fsc->fdblocks += blocks - 1;
+
+       error = xfs_btree_count_blocks(sc->sa.cnt_cur, &blocks);
+       if (error)
+               goto out_free;
+       fsc->fdblocks += blocks - 1;
+
+out_free:
+       xchk_ag_free(sc, &sc->sa);
+       return error;
+}
+
 /*
  * Calculate what the global in-core counters ought to be from the incore
  * per-AG structure.  Callers can compare this to the actual in-core counters
@@ -182,8 +212,15 @@ retry:
                /* Add up the free/freelist/bnobt/cntbt blocks */
                fsc->fdblocks += pag->pagf_freeblks;
                fsc->fdblocks += pag->pagf_flcount;
-               if (xfs_sb_version_haslazysbcount(&sc->mp->m_sb))
+               if (xfs_sb_version_haslazysbcount(&sc->mp->m_sb)) {
                        fsc->fdblocks += pag->pagf_btreeblks;
+               } else {
+                       error = xchk_fscount_btreeblks(sc, fsc, agno);
+                       if (error) {
+                               xfs_perag_put(pag);
+                               break;
+                       }
+               }
 
                /*
                 * Per-AG reservations are taken out of the incore counters,