[PATCH 7/9] xfs_scrub: check dependencies of a scrub type before repairing

Darrick J. Wong
2023-12-31T22:42:11Z

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@kernel.org>
---
scrub/repair.c | 32 ++++++++++++++++++++++++++++++++
scrub/scrub.h | 5 +++++
2 files changed, 37 insertions(+)

diff --git a/scrub/repair.c b/scrub/repair.c
index d4521f50c68..9b4b5d01626 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 f22a952629e..3ae0bfd2952 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