From: Darrick J. Wong <djwong@xxxxxxxxxx> 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 <djwong@xxxxxxxxxx> --- scrub/repair.c | 32 ++++++++++++++++++++++++++++++++ scrub/scrub.h | 5 +++++ 2 files changed, 37 insertions(+) diff --git a/scrub/repair.c b/scrub/repair.c index 9de34eada04..44e74306ba8 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 1cc638e88d7..a6f1f4c8573 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