summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 10:40:10 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-10-22 16:40:31 -0700
commit495b3bf77418fb2bf40d6b28711fc81ad90320e0 (patch)
treeca29bef042823f17071153d9d4efe6a90d4a280f
parent93563bb161f31c1e3642480de5f12445e6938025 (diff)
xfs: online checking of the free rt extent count
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 <djwong@kernel.org>
-rw-r--r--fs/xfs/scrub/fscounters.c72
-rw-r--r--fs/xfs/scrub/scrub.h1
-rw-r--r--fs/xfs/scrub/trace.h19
3 files changed, 92 insertions, 0 deletions
diff --git a/fs/xfs/scrub/fscounters.c b/fs/xfs/scrub/fscounters.c
index 48a6cbdf95d0..5761fa94964a 100644
--- a/fs/xfs/scrub/fscounters.c
+++ b/fs/xfs/scrub/fscounters.c
@@ -14,6 +14,8 @@
#include "xfs_health.h"
#include "xfs_btree.h"
#include "xfs_ag.h"
+#include "xfs_rtalloc.h"
+#include "xfs_inode.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/trace.h"
@@ -267,6 +269,71 @@ retry:
return 0;
}
+#ifdef CONFIG_XFS_RT
+static inline int
+xchk_fscount_add_frextent(
+ struct xfs_trans *tp,
+ const 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_has_realtime(mp)) {
+ if (mp->m_sb.sb_frextents != 0)
+ xchk_set_corrupt(sc);
+ 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);
+
+ trace_xchk_fscounters_frextents_within_range(sc->mp, fsc->frextents,
+ mp->m_sb.sb_frextents);
+
+ 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;
+}
+#else
+STATIC int
+xchk_fscount_check_frextents(
+ struct xfs_scrub *sc,
+ struct xchk_fscounters *fsc)
+{
+ struct xfs_mount *mp = sc->mp;
+
+ if (mp->m_sb.sb_frextents != 0)
+ xchk_set_corrupt(sc);
+
+ return 0;
+}
+#endif /* CONFIG_XFS_RT */
+
/*
* Is the @counter reasonably close to the @expected value?
*
@@ -378,5 +445,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 3de5287e98d8..dd45dbcbc05d 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -165,6 +165,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;
};
diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h
index a7bbb84f91a7..ec205248afad 100644
--- a/fs/xfs/scrub/trace.h
+++ b/fs/xfs/scrub/trace.h
@@ -657,6 +657,25 @@ TRACE_EVENT(xchk_fscounters_within_range,
__entry->old_value)
)
+TRACE_EVENT(xchk_fscounters_frextents_within_range,
+ TP_PROTO(struct xfs_mount *mp, uint64_t expected, int64_t curr_value),
+ TP_ARGS(mp, expected, curr_value),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(uint64_t, expected)
+ __field(int64_t, curr_value)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->expected = expected;
+ __entry->curr_value = curr_value;
+ ),
+ TP_printk("dev %d:%d expected %llu curr_value %lld",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->expected,
+ __entry->curr_value)
+)
+
/* repair tracepoints */
#if IS_ENABLED(CONFIG_XFS_ONLINE_REPAIR)