]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - scrub/phase4.c
xfs_scrub: remove moveon from main program
[thirdparty/xfsprogs-dev.git] / scrub / phase4.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 */
6 #include "xfs.h"
7 #include <stdint.h>
8 #include <dirent.h>
9 #include <sys/types.h>
10 #include <sys/statvfs.h>
11 #include "list.h"
12 #include "libfrog/paths.h"
13 #include "libfrog/workqueue.h"
14 #include "xfs_scrub.h"
15 #include "common.h"
16 #include "progress.h"
17 #include "scrub.h"
18 #include "repair.h"
19 #include "vfs.h"
20
21 /* Phase 4: Repair filesystem. */
22
23 /* Fix all the problems in our per-AG list. */
24 static void
25 repair_ag(
26 struct workqueue *wq,
27 xfs_agnumber_t agno,
28 void *priv)
29 {
30 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
31 bool *aborted = priv;
32 struct action_list *alist;
33 size_t unfixed;
34 size_t new_unfixed;
35 unsigned int flags = 0;
36 int ret;
37
38 alist = &ctx->action_lists[agno];
39 unfixed = action_list_length(alist);
40
41 /* Repair anything broken until we fail to make progress. */
42 do {
43 ret = action_list_process(ctx, ctx->mnt.fd, alist, flags);
44 if (ret) {
45 *aborted = true;
46 return;
47 }
48 new_unfixed = action_list_length(alist);
49 if (new_unfixed == unfixed)
50 break;
51 unfixed = new_unfixed;
52 if (*aborted)
53 return;
54 } while (unfixed > 0);
55
56 /* Try once more, but this time complain if we can't fix things. */
57 flags |= ALP_COMPLAIN_IF_UNFIXED;
58 ret = action_list_process(ctx, ctx->mnt.fd, alist, flags);
59 if (ret)
60 *aborted = true;
61 }
62
63 /* Process all the action items. */
64 static int
65 repair_everything(
66 struct scrub_ctx *ctx)
67 {
68 struct workqueue wq;
69 xfs_agnumber_t agno;
70 bool aborted = false;
71 int ret;
72
73 ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
74 scrub_nproc_workqueue(ctx));
75 if (ret) {
76 str_liberror(ctx, ret, _("creating repair workqueue"));
77 return ret;
78 }
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"));
86 break;
87 }
88 }
89
90 ret = workqueue_terminate(&wq);
91 if (ret)
92 str_liberror(ctx, ret, _("finishing repair work"));
93 workqueue_destroy(&wq);
94
95 if (aborted)
96 return ECANCELED;
97
98 pthread_mutex_lock(&ctx->lock);
99 if (ctx->corruptions_found == 0 && ctx->unfixable_errors == 0 &&
100 want_fstrim) {
101 fstrim(ctx);
102 progress_add(1);
103 }
104 pthread_mutex_unlock(&ctx->lock);
105
106 return 0;
107 }
108
109 /* Fix everything that needs fixing. */
110 int
111 phase4_func(
112 struct scrub_ctx *ctx)
113 {
114 int ret;
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 */
122 ret = xfs_scrub_fs_summary(ctx, &ctx->action_lists[0]);
123 if (ret)
124 return ret;
125
126 return repair_everything(ctx);
127 }
128
129 /* Estimate how much work we're going to do. */
130 int
131 phase4_estimate(
132 struct scrub_ctx *ctx,
133 uint64_t *items,
134 unsigned int *nr_threads,
135 int *rshift)
136 {
137 xfs_agnumber_t agno;
138 size_t need_fixing = 0;
139
140 for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
141 need_fixing += action_list_length(&ctx->action_lists[agno]);
142 need_fixing++;
143 *items = need_fixing;
144 *nr_threads = scrub_nproc(ctx) + 1;
145 *rshift = 0;
146 return 0;
147 }