]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/phase4.c
xfs_scrub: remove moveon from phase 4 functions
[thirdparty/xfsprogs-dev.git] / scrub / phase4.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0+
7e36bc0f
DW
2/*
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
7e36bc0f 4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
7e36bc0f 5 */
a440f877 6#include "xfs.h"
7e36bc0f 7#include <stdint.h>
7e36bc0f
DW
8#include <dirent.h>
9#include <sys/types.h>
7e36bc0f 10#include <sys/statvfs.h>
7e36bc0f 11#include "list.h"
42b4c8e8 12#include "libfrog/paths.h"
56598728 13#include "libfrog/workqueue.h"
7e36bc0f
DW
14#include "xfs_scrub.h"
15#include "common.h"
ed60d210 16#include "progress.h"
7e36bc0f 17#include "scrub.h"
ee310b0c 18#include "repair.h"
7e36bc0f
DW
19#include "vfs.h"
20
21/* Phase 4: Repair filesystem. */
22
ee310b0c
DW
23/* Fix all the problems in our per-AG list. */
24static void
596a30ba 25repair_ag(
ee310b0c
DW
26 struct workqueue *wq,
27 xfs_agnumber_t agno,
28 void *priv)
29{
30 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
596a30ba 31 bool *aborted = priv;
83d2c80b 32 struct action_list *alist;
ee310b0c
DW
33 size_t unfixed;
34 size_t new_unfixed;
35 unsigned int flags = 0;
83d2c80b 36 int ret;
ee310b0c
DW
37
38 alist = &ctx->action_lists[agno];
83d2c80b 39 unfixed = action_list_length(alist);
ee310b0c
DW
40
41 /* Repair anything broken until we fail to make progress. */
42 do {
83d2c80b
DW
43 ret = action_list_process(ctx, ctx->mnt.fd, alist, flags);
44 if (ret) {
596a30ba 45 *aborted = true;
ee310b0c
DW
46 return;
47 }
83d2c80b 48 new_unfixed = action_list_length(alist);
ee310b0c
DW
49 if (new_unfixed == unfixed)
50 break;
51 unfixed = new_unfixed;
596a30ba
DW
52 if (*aborted)
53 return;
54 } while (unfixed > 0);
ee310b0c
DW
55
56 /* Try once more, but this time complain if we can't fix things. */
06e49f3e 57 flags |= ALP_COMPLAIN_IF_UNFIXED;
83d2c80b
DW
58 ret = action_list_process(ctx, ctx->mnt.fd, alist, flags);
59 if (ret)
596a30ba 60 *aborted = true;
ee310b0c
DW
61}
62
7e36bc0f 63/* Process all the action items. */
596a30ba
DW
64static int
65repair_everything(
7e36bc0f
DW
66 struct scrub_ctx *ctx)
67{
ee310b0c
DW
68 struct workqueue wq;
69 xfs_agnumber_t agno;
596a30ba 70 bool aborted = false;
ee310b0c
DW
71 int ret;
72
73 ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
74 scrub_nproc_workqueue(ctx));
75 if (ret) {
9d57cbfc 76 str_liberror(ctx, ret, _("creating repair workqueue"));
596a30ba 77 return ret;
ee310b0c 78 }
596a30ba
DW
79 for (agno = 0; !aborted && agno < ctx->mnt.fsgeom.agcount; agno++) {
80 if (action_list_length(&ctx->action_lists[agno]) == 0)
81 continue;
82
83 ret = workqueue_add(&wq, repair_ag, agno, &aborted);
84 if (ret) {
85 str_liberror(ctx, ret, _("queueing repair work"));
ee310b0c 86 break;
596a30ba 87 }
ee310b0c 88 }
71296cf8
DW
89
90 ret = workqueue_terminate(&wq);
596a30ba 91 if (ret)
71296cf8 92 str_liberror(ctx, ret, _("finishing repair work"));
ee310b0c 93 workqueue_destroy(&wq);
7e36bc0f 94
596a30ba
DW
95 if (aborted)
96 return ECANCELED;
97
7e36bc0f 98 pthread_mutex_lock(&ctx->lock);
596a30ba 99 if (ctx->corruptions_found == 0 && ctx->unfixable_errors == 0 &&
49e05cb0 100 want_fstrim) {
7e36bc0f 101 fstrim(ctx);
ed60d210
DW
102 progress_add(1);
103 }
7e36bc0f
DW
104 pthread_mutex_unlock(&ctx->lock);
105
596a30ba 106 return 0;
7e36bc0f
DW
107}
108
109/* Fix everything that needs fixing. */
596a30ba
DW
110int
111phase4_func(
d22f2471 112 struct scrub_ctx *ctx)
7e36bc0f 113{
d22f2471 114 int ret;
cbaf1c9d
DW
115
116 /*
117 * Check the summary counters early. Normally we do this during phase
118 * seven, but some of the cross-referencing requires fairly-accurate
119 * counters, so counter repairs have to be put on the list now so that
120 * they get fixed before we stop retrying unfixed metadata repairs.
121 */
d22f2471
DW
122 ret = xfs_scrub_fs_summary(ctx, &ctx->action_lists[0]);
123 if (ret)
596a30ba 124 return ret;
cbaf1c9d 125
596a30ba 126 return repair_everything(ctx);
7e36bc0f
DW
127}
128
ed60d210 129bool
596a30ba
DW
130xfs_repair_fs(
131 struct scrub_ctx *ctx)
132{
133 return phase4_func(ctx) == 0;
134}
135
136/* Estimate how much work we're going to do. */
137int
138phase4_estimate(
ed60d210
DW
139 struct scrub_ctx *ctx,
140 uint64_t *items,
141 unsigned int *nr_threads,
142 int *rshift)
143{
ee310b0c
DW
144 xfs_agnumber_t agno;
145 size_t need_fixing = 0;
146
3f9efb2e 147 for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
83d2c80b 148 need_fixing += action_list_length(&ctx->action_lists[agno]);
ee310b0c
DW
149 need_fixing++;
150 *items = need_fixing;
151 *nr_threads = scrub_nproc(ctx) + 1;
ed60d210 152 *rshift = 0;
596a30ba
DW
153 return 0;
154}
155
156bool
157xfs_estimate_repair_work(
158 struct scrub_ctx *ctx,
159 uint64_t *items,
160 unsigned int *nr_threads,
161 int *rshift)
162{
163 return phase4_estimate(ctx, items, nr_threads, rshift) == 0;
ed60d210 164}