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-09-17 18:54:47 -0700
commitb40599a9e7135ccf6ace9944f60ddd3738549056 (patch)
tree058db14959240708b46534489586c1127502e49f
parentaf8b676f92ef751a4a1eab01ec7b07f854029b08 (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.c54
-rw-r--r--fs/xfs/scrub/scrub.h1
-rw-r--r--fs/xfs/scrub/trace.h19
3 files changed, 74 insertions, 0 deletions
diff --git a/fs/xfs/scrub/fscounters.c b/fs/xfs/scrub/fscounters.c
index 48a6cbdf95d0..c74bc9f96b8f 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,53 @@ retry:
return 0;
}
+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))
+ 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;
+}
+
/*
* Is the @counter reasonably close to the @expected value?
*
@@ -378,5 +427,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 80e5026bba44..820de2121e5d 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -166,6 +166,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)