From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Teach scrub to ask the kernel to check and repair summary counters during phase 7. Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Reviewed-by: Dave Chinner <dchinner@xxxxxxxxxx> --- scrub/phase4.c | 12 ++++++++++++ scrub/phase7.c | 14 ++++++++++++++ scrub/repair.c | 3 +++ scrub/scrub.c | 12 ++++++++++++ scrub/scrub.h | 2 ++ 5 files changed, 43 insertions(+) diff --git a/scrub/phase4.c b/scrub/phase4.c index 589777f6..25fedc83 100644 --- a/scrub/phase4.c +++ b/scrub/phase4.c @@ -107,6 +107,18 @@ bool xfs_repair_fs( struct scrub_ctx *ctx) { + bool moveon; + + /* + * Check the summary counters early. Normally we do this during phase + * seven, but some of the cross-referencing requires fairly-accurate + * counters, so counter repairs have to be put on the list now so that + * they get fixed before we stop retrying unfixed metadata repairs. + */ + moveon = xfs_scrub_fs_summary(ctx, &ctx->action_lists[0]); + if (!moveon) + return false; + return xfs_process_action_items(ctx); } diff --git a/scrub/phase7.c b/scrub/phase7.c index f82b60d6..308b8bb3 100644 --- a/scrub/phase7.c +++ b/scrub/phase7.c @@ -9,10 +9,13 @@ #include <sys/statvfs.h> #include "libfrog/paths.h" #include "libfrog/ptvar.h" +#include "list.h" #include "xfs_scrub.h" #include "common.h" +#include "scrub.h" #include "fscounters.h" #include "spacemap.h" +#include "repair.h" /* Phase 7: Check summary counters. */ @@ -91,6 +94,7 @@ xfs_scan_summary( struct scrub_ctx *ctx) { struct summary_counts totalcount = {0}; + struct xfs_action_list alist; struct ptvar *ptvar; unsigned long long used_data; unsigned long long used_rt; @@ -110,6 +114,16 @@ xfs_scan_summary( int ip; int error; + /* Check and fix the fs summary counters. */ + xfs_action_list_init(&alist); + moveon = xfs_scrub_fs_summary(ctx, &alist); + if (!moveon) + return false; + moveon = xfs_action_list_process(ctx, ctx->mnt.fd, &alist, + ALP_COMPLAIN_IF_UNFIXED | ALP_NOPROGRESS); + if (!moveon) + return moveon; + /* Flush everything out to disk before we start counting. */ error = syncfs(ctx->mnt.fd); if (error) { diff --git a/scrub/repair.c b/scrub/repair.c index 0e5afb20..04a9dccf 100644 --- a/scrub/repair.c +++ b/scrub/repair.c @@ -84,6 +84,9 @@ xfs_action_item_priority( case XFS_SCRUB_TYPE_GQUOTA: case XFS_SCRUB_TYPE_PQUOTA: return PRIO(aitem, XFS_SCRUB_TYPE_UQUOTA); + case XFS_SCRUB_TYPE_FSCOUNTERS: + /* This should always go after AG headers no matter what. */ + return PRIO(aitem, INT_MAX); } abort(); } diff --git a/scrub/scrub.c b/scrub/scrub.c index 2557da2a..d7a6b49b 100644 --- a/scrub/scrub.c +++ b/scrub/scrub.c @@ -388,6 +388,18 @@ xfs_scrub_fs_metadata( return xfs_scrub_all_types(ctx, XFROG_SCRUB_TYPE_FS, 0, alist); } +/* Scrub FS summary metadata. */ +bool +xfs_scrub_fs_summary( + struct scrub_ctx *ctx, + struct xfs_action_list *alist) +{ + int ret; + + ret = xfs_scrub_meta_type(ctx, XFS_SCRUB_TYPE_FSCOUNTERS, 0, alist); + return ret == 0; +} + /* How many items do we have to check? */ unsigned int xfs_scrub_estimate_ag_work( diff --git a/scrub/scrub.h b/scrub/scrub.h index 7e28b522..d407abb0 100644 --- a/scrub/scrub.h +++ b/scrub/scrub.h @@ -25,6 +25,8 @@ bool xfs_scrub_ag_metadata(struct scrub_ctx *ctx, xfs_agnumber_t agno, struct xfs_action_list *alist); bool xfs_scrub_fs_metadata(struct scrub_ctx *ctx, struct xfs_action_list *alist); +bool xfs_scrub_fs_summary(struct scrub_ctx *ctx, + struct xfs_action_list *alist); bool xfs_can_scrub_fs_metadata(struct scrub_ctx *ctx); bool xfs_can_scrub_inode(struct scrub_ctx *ctx);