From: Darrick J. Wong Date: Mon, 29 Jul 2024 23:23:06 +0000 (-0700) Subject: xfs_scrub: check dependencies of a scrub type before repairing X-Git-Tag: v6.10.0~18^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=98c23e97785b517a236c57709092d2f4c1875e2c;p=thirdparty%2Fxfsprogs-dev.git xfs_scrub: check dependencies of a scrub type before repairing Now that we have a map of a scrub type to its dependent scrub types, use this information to avoid trying to fix higher level metadata before the lower levels have passed. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- diff --git a/scrub/repair.c b/scrub/repair.c index d4521f50..9b4b5d01 100644 --- a/scrub/repair.c +++ b/scrub/repair.c @@ -497,6 +497,29 @@ action_list_process( return ret; } +/* Decide if the dependent scrub types of the given scrub type are ok. */ +static bool +repair_item_dependencies_ok( + const struct scrub_item *sri, + unsigned int scrub_type) +{ + unsigned int dep_mask = repair_deps[scrub_type]; + unsigned int b; + + for (b = 0; dep_mask && b < XFS_SCRUB_TYPE_NR; b++, dep_mask >>= 1) { + if (!(dep_mask & 1)) + continue; + /* + * If this lower level object also needs repair, we can't fix + * the higher level item. + */ + if (sri->sri_state[b] & SCRUB_ITEM_NEEDSREPAIR) + return false; + } + + return true; +} + /* * For a given filesystem object, perform all repairs of a given class * (corrupt, xcorrupt, xfail, preen) if the repair item says it's needed. @@ -536,6 +559,15 @@ repair_item_class( if (!(sri->sri_state[scrub_type] & repair_mask)) continue; + /* + * Don't try to repair higher level items if their lower-level + * dependencies haven't been verified, unless this is our last + * chance to fix things without complaint. + */ + if (!(flags & XRM_FINAL_WARNING) && + !repair_item_dependencies_ok(sri, scrub_type)) + continue; + fix = xfs_repair_metadata(ctx, xfdp, scrub_type, sri, flags); switch (fix) { case CHECK_DONE: diff --git a/scrub/scrub.h b/scrub/scrub.h index f22a9526..3ae0bfd2 100644 --- a/scrub/scrub.h +++ b/scrub/scrub.h @@ -43,6 +43,11 @@ enum check_outcome { #define SCRUB_ITEM_REPAIR_XREF (SCRUB_ITEM_XFAIL | \ SCRUB_ITEM_XCORRUPT) +/* Mask of bits signalling that a piece of metadata requires attention. */ +#define SCRUB_ITEM_NEEDSREPAIR (SCRUB_ITEM_CORRUPT | \ + SCRUB_ITEM_XFAIL | \ + SCRUB_ITEM_XCORRUPT) + struct scrub_item { /* * Information we need to call the scrub and repair ioctls. Per-AG