]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - scrub/phase4.c
xfs_scrub: remove moveon from main program
[thirdparty/xfsprogs-dev.git] / scrub / phase4.c
index 0e00c94c91fec9d75833a13705392e59faf75460..1c1de906c1d804bc392a34063caf6a216136cdf3 100644 (file)
 #include <sys/types.h>
 #include <sys/statvfs.h>
 #include "list.h"
-#include "path.h"
-#include "workqueue.h"
+#include "libfrog/paths.h"
+#include "libfrog/workqueue.h"
 #include "xfs_scrub.h"
 #include "common.h"
 #include "progress.h"
 #include "scrub.h"
+#include "repair.h"
 #include "vfs.h"
 
 /* Phase 4: Repair filesystem. */
 
+/* Fix all the problems in our per-AG list. */
+static void
+repair_ag(
+       struct workqueue                *wq,
+       xfs_agnumber_t                  agno,
+       void                            *priv)
+{
+       struct scrub_ctx                *ctx = (struct scrub_ctx *)wq->wq_ctx;
+       bool                            *aborted = priv;
+       struct action_list              *alist;
+       size_t                          unfixed;
+       size_t                          new_unfixed;
+       unsigned int                    flags = 0;
+       int                             ret;
+
+       alist = &ctx->action_lists[agno];
+       unfixed = action_list_length(alist);
+
+       /* Repair anything broken until we fail to make progress. */
+       do {
+               ret = action_list_process(ctx, ctx->mnt.fd, alist, flags);
+               if (ret) {
+                       *aborted = true;
+                       return;
+               }
+               new_unfixed = action_list_length(alist);
+               if (new_unfixed == unfixed)
+                       break;
+               unfixed = new_unfixed;
+               if (*aborted)
+                       return;
+       } while (unfixed > 0);
+
+       /* Try once more, but this time complain if we can't fix things. */
+       flags |= ALP_COMPLAIN_IF_UNFIXED;
+       ret = action_list_process(ctx, ctx->mnt.fd, alist, flags);
+       if (ret)
+               *aborted = true;
+}
+
 /* Process all the action items. */
-static bool
-xfs_process_action_items(
+static int
+repair_everything(
        struct scrub_ctx                *ctx)
 {
-       bool                            moveon = true;
+       struct workqueue                wq;
+       xfs_agnumber_t                  agno;
+       bool                            aborted = false;
+       int                             ret;
+
+       ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
+                       scrub_nproc_workqueue(ctx));
+       if (ret) {
+               str_liberror(ctx, ret, _("creating repair workqueue"));
+               return ret;
+       }
+       for (agno = 0; !aborted && agno < ctx->mnt.fsgeom.agcount; agno++) {
+               if (action_list_length(&ctx->action_lists[agno]) == 0)
+                       continue;
+
+               ret = workqueue_add(&wq, repair_ag, agno, &aborted);
+               if (ret) {
+                       str_liberror(ctx, ret, _("queueing repair work"));
+                       break;
+               }
+       }
+
+       ret = workqueue_terminate(&wq);
+       if (ret)
+               str_liberror(ctx, ret, _("finishing repair work"));
+       workqueue_destroy(&wq);
+
+       if (aborted)
+               return ECANCELED;
 
        pthread_mutex_lock(&ctx->lock);
-       if (moveon && ctx->errors_found == 0 && want_fstrim) {
+       if (ctx->corruptions_found == 0 && ctx->unfixable_errors == 0 &&
+           want_fstrim) {
                fstrim(ctx);
                progress_add(1);
        }
        pthread_mutex_unlock(&ctx->lock);
 
-       return moveon;
+       return 0;
 }
 
 /* Fix everything that needs fixing. */
-bool
-xfs_repair_fs(
-       struct scrub_ctx                *ctx)
+int
+phase4_func(
+       struct scrub_ctx        *ctx)
 {
-       return xfs_process_action_items(ctx);
+       int                     ret;
+
+       /*
+        * Check the summary counters early.  Normally we do this during phase
+        * seven, but some of the cross-referencing requires fairly-accurate
+        * counters, so counter repairs have to be put on the list now so that
+        * they get fixed before we stop retrying unfixed metadata repairs.
+        */
+       ret = xfs_scrub_fs_summary(ctx, &ctx->action_lists[0]);
+       if (ret)
+               return ret;
+
+       return repair_everything(ctx);
 }
 
 /* Estimate how much work we're going to do. */
-bool
-xfs_estimate_repair_work(
+int
+phase4_estimate(
        struct scrub_ctx        *ctx,
        uint64_t                *items,
        unsigned int            *nr_threads,
        int                     *rshift)
 {
-       *items = 1;
-       *nr_threads = 1;
+       xfs_agnumber_t          agno;
+       size_t                  need_fixing = 0;
+
+       for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
+               need_fixing += action_list_length(&ctx->action_lists[agno]);
+       need_fixing++;
+       *items = need_fixing;
+       *nr_threads = scrub_nproc(ctx) + 1;
        *rshift = 0;
-       return true;
+       return 0;
 }