]> git.apps.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_scrub: move repair functions to repair.c
authorDarrick J. Wong <djwong@kernel.org>
Mon, 29 Jul 2024 23:23:02 +0000 (16:23 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:01:06 +0000 (17:01 -0700)
Move all the repair functions to repair.c.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
scrub/phase1.c
scrub/repair.c
scrub/scrub.c
scrub/scrub.h
scrub/scrub_private.h [new file with mode: 0644]

index 96138e03e71c792626eab8816f17ef9d4891cf51..81b0918a1c8a4dc9da99a322ad3dddbeb0525fa2 100644 (file)
@@ -210,7 +210,7 @@ _("Kernel metadata scrubbing facility is not available."));
        }
 
        /* Do we need kernel-assisted metadata repair? */
-       if (ctx->mode != SCRUB_MODE_DRY_RUN && !xfs_can_repair(ctx)) {
+       if (ctx->mode != SCRUB_MODE_DRY_RUN && !can_repair(ctx)) {
                str_error(ctx, ctx->mntpoint,
 _("Kernel metadata repair facility is not available.  Use -n to scrub."));
                return ECANCELED;
index 61d62ab6b49287588ded101be465de1c0126c75a..54bd09575c0f304b2813775ea867839e42332578 100644 (file)
 #include <sys/statvfs.h>
 #include "list.h"
 #include "libfrog/paths.h"
+#include "libfrog/fsgeom.h"
+#include "libfrog/scrub.h"
 #include "xfs_scrub.h"
 #include "common.h"
 #include "scrub.h"
 #include "progress.h"
 #include "repair.h"
+#include "descr.h"
+#include "scrub_private.h"
+
+/* General repair routines. */
+
+/* Repair some metadata. */
+static enum check_outcome
+xfs_repair_metadata(
+       struct scrub_ctx                *ctx,
+       struct xfs_fd                   *xfdp,
+       struct action_item              *aitem,
+       unsigned int                    repair_flags)
+{
+       struct xfs_scrub_metadata       meta = { 0 };
+       struct xfs_scrub_metadata       oldm;
+       DEFINE_DESCR(dsc, ctx, format_scrub_descr);
+       int                             error;
+
+       assert(aitem->type < XFS_SCRUB_TYPE_NR);
+       assert(!debug_tweak_on("XFS_SCRUB_NO_KERNEL"));
+       meta.sm_type = aitem->type;
+       meta.sm_flags = aitem->flags | XFS_SCRUB_IFLAG_REPAIR;
+       if (use_force_rebuild)
+               meta.sm_flags |= XFS_SCRUB_IFLAG_FORCE_REBUILD;
+       switch (xfrog_scrubbers[aitem->type].group) {
+       case XFROG_SCRUB_GROUP_AGHEADER:
+       case XFROG_SCRUB_GROUP_PERAG:
+               meta.sm_agno = aitem->agno;
+               break;
+       case XFROG_SCRUB_GROUP_INODE:
+               meta.sm_ino = aitem->ino;
+               meta.sm_gen = aitem->gen;
+               break;
+       default:
+               break;
+       }
+
+       if (!is_corrupt(&meta) && (repair_flags & XRM_REPAIR_ONLY))
+               return CHECK_RETRY;
+
+       memcpy(&oldm, &meta, sizeof(oldm));
+       descr_set(&dsc, &oldm);
+
+       if (needs_repair(&meta))
+               str_info(ctx, descr_render(&dsc), _("Attempting repair."));
+       else if (debug || verbose)
+               str_info(ctx, descr_render(&dsc),
+                               _("Attempting optimization."));
+
+       error = -xfrog_scrub_metadata(xfdp, &meta);
+       switch (error) {
+       case 0:
+               /* No operational errors encountered. */
+               break;
+       case EDEADLOCK:
+       case EBUSY:
+               /* Filesystem is busy, try again later. */
+               if (debug || verbose)
+                       str_info(ctx, descr_render(&dsc),
+_("Filesystem is busy, deferring repair."));
+               return CHECK_RETRY;
+       case ESHUTDOWN:
+               /* Filesystem is already shut down, abort. */
+               str_error(ctx, descr_render(&dsc),
+_("Filesystem is shut down, aborting."));
+               return CHECK_ABORT;
+       case ENOTTY:
+       case EOPNOTSUPP:
+               /*
+                * If the kernel cannot perform the optimization that we
+                * requested; or we forced a repair but the kernel doesn't know
+                * how to perform the repair, don't requeue the request.  Mark
+                * it done and move on.
+                */
+               if (is_unoptimized(&oldm) ||
+                   debug_tweak_on("XFS_SCRUB_FORCE_REPAIR"))
+                       return CHECK_DONE;
+               /*
+                * If we're in no-complain mode, requeue the check for
+                * later.  It's possible that an error in another
+                * component caused us to flag an error in this
+                * component.  Even if the kernel didn't think it
+                * could fix this, it's at least worth trying the scan
+                * again to see if another repair fixed it.
+                */
+               if (!(repair_flags & XRM_FINAL_WARNING))
+                       return CHECK_RETRY;
+               fallthrough;
+       case EINVAL:
+               /* Kernel doesn't know how to repair this? */
+               str_corrupt(ctx, descr_render(&dsc),
+_("Don't know how to fix; offline repair required."));
+               return CHECK_DONE;
+       case EROFS:
+               /* Read-only filesystem, can't fix. */
+               if (verbose || debug || needs_repair(&oldm))
+                       str_error(ctx, descr_render(&dsc),
+_("Read-only filesystem; cannot make changes."));
+               return CHECK_ABORT;
+       case ENOENT:
+               /* Metadata not present, just skip it. */
+               return CHECK_DONE;
+       case ENOMEM:
+       case ENOSPC:
+               /* Don't care if preen fails due to low resources. */
+               if (is_unoptimized(&oldm) && !needs_repair(&oldm))
+                       return CHECK_DONE;
+               fallthrough;
+       default:
+               /*
+                * Operational error.  If the caller doesn't want us
+                * to complain about repair failures, tell the caller
+                * to requeue the repair for later and don't say a
+                * thing.  Otherwise, print error and bail out.
+                */
+               if (!(repair_flags & XRM_FINAL_WARNING))
+                       return CHECK_RETRY;
+               str_liberror(ctx, error, descr_render(&dsc));
+               return CHECK_DONE;
+       }
+
+       if (repair_flags & XRM_FINAL_WARNING)
+               scrub_warn_incomplete_scrub(ctx, &dsc, &meta);
+       if (needs_repair(&meta)) {
+               /*
+                * Still broken; if we've been told not to complain then we
+                * just requeue this and try again later.  Otherwise we
+                * log the error loudly and don't try again.
+                */
+               if (!(repair_flags & XRM_FINAL_WARNING))
+                       return CHECK_RETRY;
+               str_corrupt(ctx, descr_render(&dsc),
+_("Repair unsuccessful; offline repair required."));
+       } else if (xref_failed(&meta)) {
+               /*
+                * This metadata object itself looks ok, but we still noticed
+                * inconsistencies when comparing it with the other filesystem
+                * metadata.  If we're in "final warning" mode, advise the
+                * caller to run xfs_repair; otherwise, we'll keep trying to
+                * reverify the cross-referencing as repairs progress.
+                */
+               if (repair_flags & XRM_FINAL_WARNING) {
+                       str_info(ctx, descr_render(&dsc),
+ _("Seems correct but cross-referencing failed; offline repair recommended."));
+               } else {
+                       if (verbose)
+                               str_info(ctx, descr_render(&dsc),
+ _("Seems correct but cross-referencing failed; will keep checking."));
+                       return CHECK_RETRY;
+               }
+       } else {
+               /* Clean operation, no corruption detected. */
+               if (is_corrupt(&oldm))
+                       record_repair(ctx, descr_render(&dsc),
+ _("Repairs successful."));
+               else if (xref_disagrees(&oldm))
+                       record_repair(ctx, descr_render(&dsc),
+ _("Repairs successful after discrepancy in cross-referencing."));
+               else if (xref_failed(&oldm))
+                       record_repair(ctx, descr_render(&dsc),
+ _("Repairs successful after cross-referencing failure."));
+               else
+                       record_preen(ctx, descr_render(&dsc),
+ _("Optimization successful."));
+       }
+       return CHECK_DONE;
+}
 
 /*
  * Prioritize action items in order of how long we can wait.
index f4b152a1c9ca795418c6bfc808fd97234ec2886d..59583913031842219e737da050b47367f705412c 100644 (file)
 #include "scrub.h"
 #include "repair.h"
 #include "descr.h"
+#include "scrub_private.h"
 
 /* Online scrub and repair wrappers. */
 
 /* Format a scrub description. */
-static int
+int
 format_scrub_descr(
        struct scrub_ctx                *ctx,
        char                            *buf,
@@ -52,46 +53,8 @@ format_scrub_descr(
        return -1;
 }
 
-/* Predicates for scrub flag state. */
-
-static inline bool is_corrupt(struct xfs_scrub_metadata *sm)
-{
-       return sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT;
-}
-
-static inline bool is_unoptimized(struct xfs_scrub_metadata *sm)
-{
-       return sm->sm_flags & XFS_SCRUB_OFLAG_PREEN;
-}
-
-static inline bool xref_failed(struct xfs_scrub_metadata *sm)
-{
-       return sm->sm_flags & XFS_SCRUB_OFLAG_XFAIL;
-}
-
-static inline bool xref_disagrees(struct xfs_scrub_metadata *sm)
-{
-       return sm->sm_flags & XFS_SCRUB_OFLAG_XCORRUPT;
-}
-
-static inline bool is_incomplete(struct xfs_scrub_metadata *sm)
-{
-       return sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE;
-}
-
-static inline bool is_suspicious(struct xfs_scrub_metadata *sm)
-{
-       return sm->sm_flags & XFS_SCRUB_OFLAG_WARNING;
-}
-
-/* Should we fix it? */
-static inline bool needs_repair(struct xfs_scrub_metadata *sm)
-{
-       return is_corrupt(sm) || xref_disagrees(sm);
-}
-
 /* Warn about strange circumstances after scrub. */
-static inline void
+void
 scrub_warn_incomplete_scrub(
        struct scrub_ctx                *ctx,
        struct descr                    *dsc,
@@ -647,7 +610,7 @@ can_scrub_parent(
 }
 
 bool
-xfs_can_repair(
+can_repair(
        struct scrub_ctx        *ctx)
 {
        return __scrub_test(ctx, XFS_SCRUB_TYPE_PROBE, XFS_SCRUB_IFLAG_REPAIR);
@@ -660,162 +623,3 @@ can_force_rebuild(
        return __scrub_test(ctx, XFS_SCRUB_TYPE_PROBE,
                        XFS_SCRUB_IFLAG_REPAIR | XFS_SCRUB_IFLAG_FORCE_REBUILD);
 }
-
-/* General repair routines. */
-
-/* Repair some metadata. */
-enum check_outcome
-xfs_repair_metadata(
-       struct scrub_ctx                *ctx,
-       struct xfs_fd                   *xfdp,
-       struct action_item              *aitem,
-       unsigned int                    repair_flags)
-{
-       struct xfs_scrub_metadata       meta = { 0 };
-       struct xfs_scrub_metadata       oldm;
-       DEFINE_DESCR(dsc, ctx, format_scrub_descr);
-       int                             error;
-
-       assert(aitem->type < XFS_SCRUB_TYPE_NR);
-       assert(!debug_tweak_on("XFS_SCRUB_NO_KERNEL"));
-       meta.sm_type = aitem->type;
-       meta.sm_flags = aitem->flags | XFS_SCRUB_IFLAG_REPAIR;
-       if (use_force_rebuild)
-               meta.sm_flags |= XFS_SCRUB_IFLAG_FORCE_REBUILD;
-       switch (xfrog_scrubbers[aitem->type].group) {
-       case XFROG_SCRUB_GROUP_AGHEADER:
-       case XFROG_SCRUB_GROUP_PERAG:
-               meta.sm_agno = aitem->agno;
-               break;
-       case XFROG_SCRUB_GROUP_INODE:
-               meta.sm_ino = aitem->ino;
-               meta.sm_gen = aitem->gen;
-               break;
-       default:
-               break;
-       }
-
-       if (!is_corrupt(&meta) && (repair_flags & XRM_REPAIR_ONLY))
-               return CHECK_RETRY;
-
-       memcpy(&oldm, &meta, sizeof(oldm));
-       descr_set(&dsc, &oldm);
-
-       if (needs_repair(&meta))
-               str_info(ctx, descr_render(&dsc), _("Attempting repair."));
-       else if (debug || verbose)
-               str_info(ctx, descr_render(&dsc),
-                               _("Attempting optimization."));
-
-       error = -xfrog_scrub_metadata(xfdp, &meta);
-       switch (error) {
-       case 0:
-               /* No operational errors encountered. */
-               break;
-       case EDEADLOCK:
-       case EBUSY:
-               /* Filesystem is busy, try again later. */
-               if (debug || verbose)
-                       str_info(ctx, descr_render(&dsc),
-_("Filesystem is busy, deferring repair."));
-               return CHECK_RETRY;
-       case ESHUTDOWN:
-               /* Filesystem is already shut down, abort. */
-               str_error(ctx, descr_render(&dsc),
-_("Filesystem is shut down, aborting."));
-               return CHECK_ABORT;
-       case ENOTTY:
-       case EOPNOTSUPP:
-               /*
-                * If the kernel cannot perform the optimization that we
-                * requested; or we forced a repair but the kernel doesn't know
-                * how to perform the repair, don't requeue the request.  Mark
-                * it done and move on.
-                */
-               if (is_unoptimized(&oldm) ||
-                   debug_tweak_on("XFS_SCRUB_FORCE_REPAIR"))
-                       return CHECK_DONE;
-               /*
-                * If we're in no-complain mode, requeue the check for
-                * later.  It's possible that an error in another
-                * component caused us to flag an error in this
-                * component.  Even if the kernel didn't think it
-                * could fix this, it's at least worth trying the scan
-                * again to see if another repair fixed it.
-                */
-               if (!(repair_flags & XRM_FINAL_WARNING))
-                       return CHECK_RETRY;
-               fallthrough;
-       case EINVAL:
-               /* Kernel doesn't know how to repair this? */
-               str_corrupt(ctx, descr_render(&dsc),
-_("Don't know how to fix; offline repair required."));
-               return CHECK_DONE;
-       case EROFS:
-               /* Read-only filesystem, can't fix. */
-               if (verbose || debug || needs_repair(&oldm))
-                       str_error(ctx, descr_render(&dsc),
-_("Read-only filesystem; cannot make changes."));
-               return CHECK_ABORT;
-       case ENOENT:
-               /* Metadata not present, just skip it. */
-               return CHECK_DONE;
-       case ENOMEM:
-       case ENOSPC:
-               /* Don't care if preen fails due to low resources. */
-               if (is_unoptimized(&oldm) && !needs_repair(&oldm))
-                       return CHECK_DONE;
-               fallthrough;
-       default:
-               /*
-                * Operational error.  If the caller doesn't want us
-                * to complain about repair failures, tell the caller
-                * to requeue the repair for later and don't say a
-                * thing.  Otherwise, print error and bail out.
-                */
-               if (!(repair_flags & XRM_FINAL_WARNING))
-                       return CHECK_RETRY;
-               str_liberror(ctx, error, descr_render(&dsc));
-               return CHECK_DONE;
-       }
-
-       if (repair_flags & XRM_FINAL_WARNING)
-               scrub_warn_incomplete_scrub(ctx, &dsc, &meta);
-       if (needs_repair(&meta)) {
-               /*
-                * Still broken; if we've been told not to complain then we
-                * just requeue this and try again later.  Otherwise we
-                * log the error loudly and don't try again.
-                */
-               if (!(repair_flags & XRM_FINAL_WARNING))
-                       return CHECK_RETRY;
-               str_corrupt(ctx, descr_render(&dsc),
-_("Repair unsuccessful; offline repair required."));
-       } else if (xref_failed(&meta)) {
-               /*
-                * This metadata object itself looks ok, but we still noticed
-                * inconsistencies when comparing it with the other filesystem
-                * metadata.  If we're in "final warning" mode, advise the
-                * caller to run xfs_repair; otherwise, we'll keep trying to
-                * reverify the cross-referencing as repairs progress.
-                */
-               if (repair_flags & XRM_FINAL_WARNING) {
-                       str_info(ctx, descr_render(&dsc),
- _("Seems correct but cross-referencing failed; offline repair recommended."));
-               } else {
-                       if (verbose)
-                               str_info(ctx, descr_render(&dsc),
- _("Seems correct but cross-referencing failed; will keep checking."));
-                       return CHECK_RETRY;
-               }
-       } else {
-               /* Clean operation, no corruption detected. */
-               if (needs_repair(&oldm))
-                       record_repair(ctx, descr_render(&dsc),
-                                       _("Repairs successful."));
-               else
-                       record_preen(ctx, descr_render(&dsc),
-                                       _("Optimization successful."));
-       }
-       return CHECK_DONE;
-}
index 5359548b06f7a018128cc70dea92ce441d37dd07..133445e8da6cb76e719d2f842d4dd3c775eeb89d 100644 (file)
@@ -38,7 +38,7 @@ bool can_scrub_dir(struct scrub_ctx *ctx);
 bool can_scrub_attr(struct scrub_ctx *ctx);
 bool can_scrub_symlink(struct scrub_ctx *ctx);
 bool can_scrub_parent(struct scrub_ctx *ctx);
-bool xfs_can_repair(struct scrub_ctx *ctx);
+bool can_repair(struct scrub_ctx *ctx);
 bool can_force_rebuild(struct scrub_ctx *ctx);
 
 int scrub_file(struct scrub_ctx *ctx, int fd, const struct xfs_bulkstat *bstat,
@@ -54,8 +54,4 @@ struct action_item {
        __u32                   agno;
 };
 
-enum check_outcome xfs_repair_metadata(struct scrub_ctx *ctx,
-               struct xfs_fd *xfdp, struct action_item *aitem,
-               unsigned int repair_flags);
-
 #endif /* XFS_SCRUB_SCRUB_H_ */
diff --git a/scrub/scrub_private.h b/scrub/scrub_private.h
new file mode 100644 (file)
index 0000000..a24d485
--- /dev/null
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef XFS_SCRUB_SCRUB_PRIVATE_H_
+#define XFS_SCRUB_SCRUB_PRIVATE_H_
+
+/* Shared code between scrub.c and repair.c. */
+
+int format_scrub_descr(struct scrub_ctx *ctx, char *buf, size_t buflen,
+               void *where);
+
+/* Predicates for scrub flag state. */
+
+static inline bool is_corrupt(struct xfs_scrub_metadata *sm)
+{
+       return sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT;
+}
+
+static inline bool is_unoptimized(struct xfs_scrub_metadata *sm)
+{
+       return sm->sm_flags & XFS_SCRUB_OFLAG_PREEN;
+}
+
+static inline bool xref_failed(struct xfs_scrub_metadata *sm)
+{
+       return sm->sm_flags & XFS_SCRUB_OFLAG_XFAIL;
+}
+
+static inline bool xref_disagrees(struct xfs_scrub_metadata *sm)
+{
+       return sm->sm_flags & XFS_SCRUB_OFLAG_XCORRUPT;
+}
+
+static inline bool is_incomplete(struct xfs_scrub_metadata *sm)
+{
+       return sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE;
+}
+
+static inline bool is_suspicious(struct xfs_scrub_metadata *sm)
+{
+       return sm->sm_flags & XFS_SCRUB_OFLAG_WARNING;
+}
+
+/* Should we fix it? */
+static inline bool needs_repair(struct xfs_scrub_metadata *sm)
+{
+       return is_corrupt(sm) || xref_disagrees(sm);
+}
+
+void scrub_warn_incomplete_scrub(struct scrub_ctx *ctx, struct descr *dsc,
+               struct xfs_scrub_metadata *meta);
+
+#endif /* XFS_SCRUB_SCRUB_PRIVATE_H_ */