]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/phase2.c
xfs_scrub: remove moveon from repair action list helpers
[thirdparty/xfsprogs-dev.git] / scrub / phase2.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0+
e758ad01
DW
2/*
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
e758ad01 4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
e758ad01 5 */
a440f877 6#include "xfs.h"
e758ad01 7#include <stdint.h>
e758ad01 8#include <sys/types.h>
e758ad01 9#include <sys/statvfs.h>
19852474 10#include "list.h"
42b4c8e8 11#include "libfrog/paths.h"
56598728 12#include "libfrog/workqueue.h"
e758ad01
DW
13#include "xfs_scrub.h"
14#include "common.h"
15#include "scrub.h"
ee310b0c 16#include "repair.h"
e758ad01
DW
17
18/* Phase 2: Check internal metadata. */
19
20/* Scrub each AG's metadata btrees. */
21static void
22xfs_scan_ag_metadata(
23 struct workqueue *wq,
24 xfs_agnumber_t agno,
25 void *arg)
26{
27 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
28 bool *pmoveon = arg;
83d2c80b
DW
29 struct action_list alist;
30 struct action_list immediate_alist;
ee310b0c
DW
31 unsigned long long broken_primaries;
32 unsigned long long broken_secondaries;
e758ad01 33 char descr[DESCR_BUFSZ];
d22f2471 34 int ret;
e758ad01 35
83d2c80b
DW
36 action_list_init(&alist);
37 action_list_init(&immediate_alist);
e758ad01
DW
38 snprintf(descr, DESCR_BUFSZ, _("AG %u"), agno);
39
40 /*
41 * First we scrub and fix the AG headers, because we need
42 * them to work well enough to check the AG btrees.
43 */
d22f2471
DW
44 ret = xfs_scrub_ag_headers(ctx, agno, &alist);
45 if (ret)
ee310b0c
DW
46 goto err;
47
48 /* Repair header damage. */
83d2c80b
DW
49 ret = action_list_process_or_defer(ctx, agno, &alist);
50 if (ret)
e758ad01
DW
51 goto err;
52
53 /* Now scrub the AG btrees. */
d22f2471
DW
54 ret = xfs_scrub_ag_metadata(ctx, agno, &alist);
55 if (ret)
ee310b0c
DW
56 goto err;
57
58 /*
59 * Figure out if we need to perform early fixing. The only
60 * reason we need to do this is if the inobt is broken, which
61 * prevents phase 3 (inode scan) from running. We can rebuild
62 * the inobt from rmapbt data, but if the rmapbt is broken even
63 * at this early phase then we are sunk.
64 */
65 broken_secondaries = 0;
66 broken_primaries = 0;
83d2c80b 67 action_list_find_mustfix(&alist, &immediate_alist,
ee310b0c
DW
68 &broken_primaries, &broken_secondaries);
69 if (broken_secondaries && !debug_tweak_on("XFS_SCRUB_FORCE_REPAIR")) {
70 if (broken_primaries)
71 str_info(ctx, descr,
72_("Corrupt primary and secondary block mapping metadata."));
73 else
74 str_info(ctx, descr,
75_("Corrupt secondary block mapping metadata."));
76 str_info(ctx, descr,
77_("Filesystem might not be repairable."));
78 }
79
80 /* Repair (inode) btree damage. */
83d2c80b
DW
81 ret = action_list_process_or_defer(ctx, agno, &immediate_alist);
82 if (ret)
e758ad01
DW
83 goto err;
84
ee310b0c 85 /* Everything else gets fixed during phase 4. */
83d2c80b 86 action_list_defer(ctx, agno, &alist);
ee310b0c 87
e758ad01
DW
88 return;
89err:
90 *pmoveon = false;
91}
92
93/* Scrub whole-FS metadata btrees. */
94static void
95xfs_scan_fs_metadata(
96 struct workqueue *wq,
97 xfs_agnumber_t agno,
98 void *arg)
99{
100 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
101 bool *pmoveon = arg;
83d2c80b 102 struct action_list alist;
d22f2471 103 int ret;
e758ad01 104
83d2c80b 105 action_list_init(&alist);
d22f2471
DW
106 ret = xfs_scrub_fs_metadata(ctx, &alist);
107 if (ret)
e758ad01 108 *pmoveon = false;
ee310b0c 109
83d2c80b 110 action_list_defer(ctx, agno, &alist);
e758ad01
DW
111}
112
113/* Scan all filesystem metadata. */
114bool
115xfs_scan_metadata(
116 struct scrub_ctx *ctx)
117{
83d2c80b 118 struct action_list alist;
e758ad01
DW
119 struct workqueue wq;
120 xfs_agnumber_t agno;
121 bool moveon = true;
122 int ret;
123
124 ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
125 scrub_nproc_workqueue(ctx));
126 if (ret) {
9d57cbfc 127 str_liberror(ctx, ret, _("creating scrub workqueue"));
e758ad01
DW
128 return false;
129 }
130
131 /*
132 * In case we ever use the primary super scrubber to perform fs
133 * upgrades (followed by a full scrub), do that before we launch
134 * anything else.
135 */
83d2c80b 136 action_list_init(&alist);
d22f2471
DW
137 ret = xfs_scrub_primary_super(ctx, &alist);
138 if (ret) {
139 moveon = false;
ee310b0c 140 goto out;
d22f2471 141 }
83d2c80b
DW
142 ret = action_list_process_or_defer(ctx, 0, &alist);
143 if (ret) {
144 moveon = false;
224df902 145 goto out;
83d2c80b 146 }
e758ad01 147
3f9efb2e 148 for (agno = 0; moveon && agno < ctx->mnt.fsgeom.agcount; agno++) {
e758ad01
DW
149 ret = workqueue_add(&wq, xfs_scan_ag_metadata, agno, &moveon);
150 if (ret) {
151 moveon = false;
9d57cbfc 152 str_liberror(ctx, ret, _("queueing per-AG scrub work"));
e758ad01
DW
153 goto out;
154 }
155 }
156
157 if (!moveon)
158 goto out;
159
160 ret = workqueue_add(&wq, xfs_scan_fs_metadata, 0, &moveon);
161 if (ret) {
162 moveon = false;
9d57cbfc 163 str_liberror(ctx, ret, _("queueing per-FS scrub work"));
e758ad01
DW
164 goto out;
165 }
166
167out:
71296cf8
DW
168 ret = workqueue_terminate(&wq);
169 if (ret) {
170 moveon = false;
171 str_liberror(ctx, ret, _("finishing scrub work"));
172 }
e758ad01
DW
173 workqueue_destroy(&wq);
174 return moveon;
175}
ed60d210
DW
176
177/* Estimate how much work we're going to do. */
178bool
179xfs_estimate_metadata_work(
180 struct scrub_ctx *ctx,
181 uint64_t *items,
182 unsigned int *nr_threads,
183 int *rshift)
184{
d22f2471 185 *items = scrub_estimate_ag_work(ctx);
ed60d210
DW
186 *nr_threads = scrub_nproc(ctx);
187 *rshift = 0;
188 return true;
189}