summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-10-25 17:14:29 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2020-10-26 18:32:11 -0700
commite4b5d9d6fd2f37df6e16dc8a5966e0bd133d4bd4 (patch)
treeff08ba41e6eafeda47f1e625bb59f5528aa0ce05
parent29af45e5fae69346e6a081020ddc8f2fb5ff3612 (diff)
xfs: online checking of the free rt extent countscrub-fixes_2020-10-26
Teach the summary count checker to count the number of free realtime extents and compare that to the superblock copy. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/scrub/fscounters.c50
-rw-r--r--fs/xfs/scrub/scrub.h1
2 files changed, 51 insertions, 0 deletions
diff --git a/fs/xfs/scrub/fscounters.c b/fs/xfs/scrub/fscounters.c
index ec2064ed3c30..e9114c4a62b4 100644
--- a/fs/xfs/scrub/fscounters.c
+++ b/fs/xfs/scrub/fscounters.c
@@ -13,6 +13,8 @@
#include "xfs_alloc.h"
#include "xfs_ialloc.h"
#include "xfs_health.h"
+#include "xfs_rtalloc.h"
+#include "xfs_inode.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/trace.h"
@@ -240,6 +242,49 @@ retry:
return 0;
}
+static int
+xchk_fscount_add_frextent(
+ struct xfs_trans *tp,
+ struct xfs_rtalloc_rec *rec,
+ void *priv)
+{
+ struct xchk_fscounters *fsc = priv;
+
+ fsc->frextents += rec->ar_extcount;
+ return 0;
+}
+
+/*
+ * Calculate what the superblock free realtime extent count should be given the
+ * realtime bitmap.
+ */
+STATIC int
+xchk_fscount_check_frextents(
+ struct xfs_scrub *sc,
+ struct xchk_fscounters *fsc)
+{
+ struct xfs_mount *mp = sc->mp;
+ int error;
+
+ if (!xfs_sb_version_hasrealtime(&mp->m_sb))
+ return 0;
+
+ fsc->frextents = 0;
+ xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_EXCL);
+ error = xfs_rtalloc_query_all(sc->tp, xchk_fscount_add_frextent, fsc);
+ if (error)
+ goto out_unlock;
+
+ spin_lock(&mp->m_sb_lock);
+ if (fsc->frextents != mp->m_sb.sb_frextents)
+ xchk_set_corrupt(sc);
+ spin_unlock(&mp->m_sb_lock);
+
+out_unlock:
+ xfs_iunlock(sc->mp->m_rbmip, XFS_ILOCK_EXCL);
+ return error;
+}
+
/*
* Is the @counter reasonably close to the @expected value?
*
@@ -351,5 +396,10 @@ xchk_fscounters(
fsc->fdblocks))
xchk_set_corrupt(sc);
+ /* Check the free extents counter for rt volumes. */
+ error = xchk_fscount_check_frextents(sc, fsc);
+ if (!xchk_process_error(sc, 0, XFS_SB_BLOCK(mp), &error))
+ return error;
+
return 0;
}
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index ad1ceb44a628..5ad442c166e8 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -157,6 +157,7 @@ struct xchk_fscounters {
uint64_t icount;
uint64_t ifree;
uint64_t fdblocks;
+ uint64_t frextents;
unsigned long long icount_min;
unsigned long long icount_max;
};