@@ -44,6 +44,40 @@ xfs_shutdown_fs(
str_errno(ctx, ctx->mntpoint);
}
+/*
+ * If we haven't found /any/ problems at all, tell the kernel that we're giving
+ * the filesystem a clean bill of health.
+ */
+static int
+report_to_kernel(
+ struct scrub_ctx *ctx)
+{
+ struct action_list alist;
+ int ret;
+
+ if (!ctx->scrub_setup_succeeded || ctx->corruptions_found ||
+ ctx->runtime_errors || ctx->unfixable_errors ||
+ ctx->warnings_found)
+ return 0;
+
+ action_list_init(&alist);
+ ret = scrub_clean_health(ctx, &alist);
+ if (ret)
+ return ret;
+
+ /*
+ * Complain if we cannot fail the clean bill of health, unless we're
+ * just testing repairs.
+ */
+ if (action_list_length(&alist) > 0 &&
+ !debug_tweak_on("XFS_SCRUB_FORCE_REPAIR")) {
+ str_info(ctx, _("Couldn't upload clean bill of health."), NULL);
+ action_list_discard(&alist);
+ }
+
+ return 0;
+}
+
/* Clean up the XFS-specific state data. */
int
scrub_cleanup(
@@ -51,6 +85,10 @@ scrub_cleanup(
{
int error;
+ error = report_to_kernel(ctx);
+ if (error)
+ return error;
+
action_lists_free(&ctx->action_lists);
if (ctx->fshandle)
free_handle(ctx->fshandle, ctx->fshandle_len);
@@ -172,6 +172,21 @@ action_lists_alloc(
return 0;
}
+/* Discard repair list contents. */
+void
+action_list_discard(
+ struct action_list *alist)
+{
+ struct action_item *aitem;
+ struct action_item *n;
+
+ list_for_each_entry_safe(aitem, n, &alist->list, list) {
+ alist->nr--;
+ list_del(&aitem->list);
+ free(aitem);
+ }
+}
+
/* Free the repair lists. */
void
action_lists_free(
@@ -24,6 +24,7 @@ static inline bool action_list_empty(const struct action_list *alist)
unsigned long long action_list_length(struct action_list *alist);
void action_list_add(struct action_list *dest, struct action_item *item);
+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,
@@ -444,6 +444,15 @@ scrub_nlinks(
return scrub_meta_type(ctx, XFS_SCRUB_TYPE_NLINKS, 0, alist);
}
+/* Update incore health records if we were clean. */
+int
+scrub_clean_health(
+ struct scrub_ctx *ctx,
+ struct action_list *alist)
+{
+ return scrub_meta_type(ctx, XFS_SCRUB_TYPE_HEALTHY, 0, alist);
+}
+
/* How many items do we have to check? */
unsigned int
scrub_estimate_ag_work(
@@ -29,6 +29,7 @@ int scrub_summary_metadata(struct scrub_ctx *ctx, struct action_list *alist);
int scrub_fs_counters(struct scrub_ctx *ctx, struct action_list *alist);
int scrub_quotacheck(struct scrub_ctx *ctx, struct action_list *alist);
int scrub_nlinks(struct scrub_ctx *ctx, struct action_list *alist);
+int scrub_clean_health(struct scrub_ctx *ctx, struct action_list *alist);
bool can_scrub_fs_metadata(struct scrub_ctx *ctx);
bool can_scrub_inode(struct scrub_ctx *ctx);