]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/phase2.c
xfs_scrub: remove moveon from main program
[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
f29dc2f5 22scan_ag_metadata(
e758ad01
DW
23 struct workqueue *wq,
24 xfs_agnumber_t agno,
25 void *arg)
26{
27 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
f29dc2f5 28 bool *aborted = 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
f29dc2f5
DW
36 if (*aborted)
37 return;
38
83d2c80b
DW
39 action_list_init(&alist);
40 action_list_init(&immediate_alist);
e758ad01
DW
41 snprintf(descr, DESCR_BUFSZ, _("AG %u"), agno);
42
43 /*
44 * First we scrub and fix the AG headers, because we need
45 * them to work well enough to check the AG btrees.
46 */
d22f2471
DW
47 ret = xfs_scrub_ag_headers(ctx, agno, &alist);
48 if (ret)
ee310b0c
DW
49 goto err;
50
51 /* Repair header damage. */
83d2c80b
DW
52 ret = action_list_process_or_defer(ctx, agno, &alist);
53 if (ret)
e758ad01
DW
54 goto err;
55
56 /* Now scrub the AG btrees. */
d22f2471
DW
57 ret = xfs_scrub_ag_metadata(ctx, agno, &alist);
58 if (ret)
ee310b0c
DW
59 goto err;
60
61 /*
62 * Figure out if we need to perform early fixing. The only
63 * reason we need to do this is if the inobt is broken, which
64 * prevents phase 3 (inode scan) from running. We can rebuild
65 * the inobt from rmapbt data, but if the rmapbt is broken even
66 * at this early phase then we are sunk.
67 */
68 broken_secondaries = 0;
69 broken_primaries = 0;
83d2c80b 70 action_list_find_mustfix(&alist, &immediate_alist,
ee310b0c
DW
71 &broken_primaries, &broken_secondaries);
72 if (broken_secondaries && !debug_tweak_on("XFS_SCRUB_FORCE_REPAIR")) {
73 if (broken_primaries)
74 str_info(ctx, descr,
75_("Corrupt primary and secondary block mapping metadata."));
76 else
77 str_info(ctx, descr,
78_("Corrupt secondary block mapping metadata."));
79 str_info(ctx, descr,
80_("Filesystem might not be repairable."));
81 }
82
83 /* Repair (inode) btree damage. */
83d2c80b
DW
84 ret = action_list_process_or_defer(ctx, agno, &immediate_alist);
85 if (ret)
e758ad01
DW
86 goto err;
87
ee310b0c 88 /* Everything else gets fixed during phase 4. */
83d2c80b 89 action_list_defer(ctx, agno, &alist);
e758ad01
DW
90 return;
91err:
f29dc2f5 92 *aborted = true;
e758ad01
DW
93}
94
95/* Scrub whole-FS metadata btrees. */
96static void
f29dc2f5 97scan_fs_metadata(
e758ad01
DW
98 struct workqueue *wq,
99 xfs_agnumber_t agno,
100 void *arg)
101{
102 struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
f29dc2f5 103 bool *aborted = arg;
83d2c80b 104 struct action_list alist;
d22f2471 105 int ret;
e758ad01 106
f29dc2f5
DW
107 if (*aborted)
108 return;
109
83d2c80b 110 action_list_init(&alist);
d22f2471 111 ret = xfs_scrub_fs_metadata(ctx, &alist);
f29dc2f5
DW
112 if (ret) {
113 *aborted = true;
114 return;
115 }
ee310b0c 116
83d2c80b 117 action_list_defer(ctx, agno, &alist);
e758ad01
DW
118}
119
120/* Scan all filesystem metadata. */
f29dc2f5
DW
121int
122phase2_func(
e758ad01
DW
123 struct scrub_ctx *ctx)
124{
83d2c80b 125 struct action_list alist;
e758ad01
DW
126 struct workqueue wq;
127 xfs_agnumber_t agno;
f29dc2f5
DW
128 bool aborted = false;
129 int ret, ret2;
e758ad01
DW
130
131 ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
132 scrub_nproc_workqueue(ctx));
133 if (ret) {
9d57cbfc 134 str_liberror(ctx, ret, _("creating scrub workqueue"));
f29dc2f5 135 return ret;
e758ad01
DW
136 }
137
138 /*
139 * In case we ever use the primary super scrubber to perform fs
140 * upgrades (followed by a full scrub), do that before we launch
141 * anything else.
142 */
83d2c80b 143 action_list_init(&alist);
d22f2471 144 ret = xfs_scrub_primary_super(ctx, &alist);
f29dc2f5 145 if (ret)
ee310b0c 146 goto out;
83d2c80b 147 ret = action_list_process_or_defer(ctx, 0, &alist);
f29dc2f5 148 if (ret)
224df902 149 goto out;
e758ad01 150
f29dc2f5
DW
151 for (agno = 0; !aborted && agno < ctx->mnt.fsgeom.agcount; agno++) {
152 ret = workqueue_add(&wq, scan_ag_metadata, agno, &aborted);
e758ad01 153 if (ret) {
9d57cbfc 154 str_liberror(ctx, ret, _("queueing per-AG scrub work"));
e758ad01
DW
155 goto out;
156 }
157 }
158
f29dc2f5 159 if (aborted)
e758ad01
DW
160 goto out;
161
f29dc2f5 162 ret = workqueue_add(&wq, scan_fs_metadata, 0, &aborted);
e758ad01 163 if (ret) {
9d57cbfc 164 str_liberror(ctx, ret, _("queueing per-FS scrub work"));
e758ad01
DW
165 goto out;
166 }
167
168out:
f29dc2f5
DW
169 ret2 = workqueue_terminate(&wq);
170 if (ret2) {
171 str_liberror(ctx, ret2, _("finishing scrub work"));
172 if (!ret && ret2)
173 ret = ret2;
71296cf8 174 }
e758ad01 175 workqueue_destroy(&wq);
f29dc2f5
DW
176
177 if (!ret && aborted)
178 ret = ECANCELED;
179 return ret;
e758ad01 180}
ed60d210 181
f29dc2f5
DW
182/* Estimate how much work we're going to do. */
183int
184phase2_estimate(
ed60d210
DW
185 struct scrub_ctx *ctx,
186 uint64_t *items,
187 unsigned int *nr_threads,
188 int *rshift)
189{
d22f2471 190 *items = scrub_estimate_ag_work(ctx);
ed60d210
DW
191 *nr_threads = scrub_nproc(ctx);
192 *rshift = 0;
f29dc2f5
DW
193 return 0;
194}