From db9143e2375c7c4a6140c0e139939584226a44dd Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 1 Sep 2021 10:40:10 -0700 Subject: 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 --- fs/xfs/scrub/fscounters.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/scrub/scrub.h | 1 + fs/xfs/scrub/trace.h | 19 +++++++++++++ 3 files changed, 92 insertions(+) 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 93ece6df02e3..552758c3a8b8 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) -- cgit v1.2.3