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