@@ -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
@@ -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;
}
/*
@@ -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