[PATCH 4/8] xfs_scrub: split up the mustfix repairs and difficulty assessment functions

Darrick J. Wong
2023-12-31T22:39:19Z

Currently, action_list_find_mustfix does two things -- it figures out
which repairs must be tried during phase 2 to enable the inode scan in
phase 3; and it figures out if xfs_scrub should warn about secondary and
primary metadata corruption that might make repair difficult.

Split these into separate functions to make each more coherent. A long
time from now we'll need this to enable warnings about difficult rt
repairs, but for now this is merely a code cleanup.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
scrub/phase2.c | 15 +++++++--------
scrub/repair.c | 38 +++++++++++++++++++++++++++-----------
scrub/repair.h | 10 +++++++---
3 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/scrub/phase2.c b/scrub/phase2.c
index ec72bb5b71a..4c0d20a8e2b 100644
--- a/scrub/phase2.c
+++ b/scrub/phase2.c
@@ -42,9 +42,8 @@ scan_ag_metadata(
struct scan_ctl *sctl = arg;
struct action_list alist;
struct action_list immediate_alist;
- unsigned long long broken_primaries;
- unsigned long long broken_secondaries;
char descr[DESCR_BUFSZ];
+ unsigned int difficulty;
int ret;

if (sctl->aborted)
@@ -79,12 +78,12 @@ scan_ag_metadata(
* the inobt from rmapbt data, but if the rmapbt is broken even
* at this early phase then we are sunk.
*/
- broken_secondaries = 0;
- broken_primaries = 0;
- action_list_find_mustfix(&alist, &immediate_alist,
- &broken_primaries, &broken_secondaries);
- if (broken_secondaries && !debug_tweak_on("XFS_SCRUB_FORCE_REPAIR")) {
- if (broken_primaries)
+ difficulty = action_list_difficulty(&alist);
+ action_list_find_mustfix(&alist, &immediate_alist);
+
+ if ((difficulty & REPAIR_DIFFICULTY_SECONDARY) &&
+ !debug_tweak_on("XFS_SCRUB_FORCE_REPAIR")) {
+ if (difficulty & REPAIR_DIFFICULTY_PRIMARY)
str_info(ctx, descr,
_("Corrupt primary and secondary block mapping metadata."));
else
diff --git a/scrub/repair.c b/scrub/repair.c
index 50f168d24fe..8ee9102ab58 100644
--- a/scrub/repair.c
+++ b/scrub/repair.c
@@ -290,9 +290,7 @@ xfs_action_item_compare(
void
action_list_find_mustfix(
struct action_list *alist,
- struct action_list *immediate_alist,
- unsigned long long *broken_primaries,
- unsigned long long *broken_secondaries)
+ struct action_list *immediate_alist)
{
struct action_item *n;
struct action_item *aitem;
@@ -301,25 +299,43 @@ action_list_find_mustfix(
if (!(aitem->flags & XFS_SCRUB_OFLAG_CORRUPT))
continue;
switch (aitem->type) {
- case XFS_SCRUB_TYPE_RMAPBT:
- (*broken_secondaries)++;
- break;
case XFS_SCRUB_TYPE_FINOBT:
case XFS_SCRUB_TYPE_INOBT:
alist->nr--;
list_move_tail(&aitem->list, &immediate_alist->list);
immediate_alist->nr++;
- fallthrough;
+ break;
+ }
+ }
+}
+
+/* Determine if primary or secondary metadata are inconsistent. */
+unsigned int
+action_list_difficulty(
+ const struct action_list *alist)
+{
+ struct action_item *aitem, *n;
+ unsigned int ret = 0;
+
+ list_for_each_entry_safe(aitem, n, &alist->list, list) {
+ if (!(aitem->flags & XFS_SCRUB_OFLAG_CORRUPT))
+ continue;
+
+ switch (aitem->type) {
+ case XFS_SCRUB_TYPE_RMAPBT:
+ ret |= REPAIR_DIFFICULTY_SECONDARY;
+ break;
+ case XFS_SCRUB_TYPE_FINOBT:
+ case XFS_SCRUB_TYPE_INOBT:
case XFS_SCRUB_TYPE_BNOBT:
case XFS_SCRUB_TYPE_CNTBT:
case XFS_SCRUB_TYPE_REFCNTBT:
- (*broken_primaries)++;
- break;
- default:
- abort();
+ ret |= REPAIR_DIFFICULTY_PRIMARY;
break;
}
}
+
+ return ret;
}

/*
diff --git a/scrub/repair.h b/scrub/repair.h
index 6b6f64691a3..b61bd29c860 100644
--- a/scrub/repair.h
+++ b/scrub/repair.h
@@ -28,9 +28,13 @@ void action_list_discard(struct action_list *alist);
void action_list_splice(struct action_list *dest, struct action_list *src);

void action_list_find_mustfix(struct action_list *actions,
- struct action_list *immediate_alist,
- unsigned long long *broken_primaries,
- unsigned long long *broken_secondaries);
+ struct action_list *immediate_alist);
+
+/* Primary metadata is corrupt */
+#define REPAIR_DIFFICULTY_PRIMARY (1U << 0)
+/* Secondary metadata is corrupt */
+#define REPAIR_DIFFICULTY_SECONDARY (1U << 1)
+unsigned int action_list_difficulty(const struct action_list *actions);

/*
* Only ask the kernel to repair this object if the kernel directly told us it