@@ -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:
@@ -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