]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/phase3.c
xfs_scrub: remove moveon from progress report helpers
[thirdparty/xfsprogs-dev.git] / scrub / phase3.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0+
fa16b376
DW
2/*
3 * Copyright (C) 2018 Oracle. All Rights Reserved.
fa16b376 4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
fa16b376 5 */
a440f877 6#include "xfs.h"
fa16b376 7#include <stdint.h>
fa16b376 8#include <sys/types.h>
fa16b376 9#include <sys/statvfs.h>
19852474 10#include "list.h"
42b4c8e8 11#include "libfrog/paths.h"
56598728 12#include "libfrog/workqueue.h"
fa16b376
DW
13#include "xfs_scrub.h"
14#include "common.h"
15#include "counter.h"
16#include "inodes.h"
ed60d210 17#include "progress.h"
fa16b376 18#include "scrub.h"
ee310b0c 19#include "repair.h"
fa16b376
DW
20
21/* Phase 3: Scan all inodes. */
22
23/*
24 * Run a per-file metadata scanner. We use the ino/gen interface to
25 * ensure that the inode we're checking matches what the inode scan
26 * told us to look at.
27 */
28static bool
29xfs_scrub_fd(
30 struct scrub_ctx *ctx,
991e5a84
DW
31 bool (*fn)(struct scrub_ctx *ctx, uint64_t ino,
32 uint32_t gen, struct xfs_action_list *a),
4cca629d 33 struct xfs_bulkstat *bs,
ee310b0c 34 struct xfs_action_list *alist)
fa16b376 35{
991e5a84 36 return fn(ctx, bs->bs_ino, bs->bs_gen, alist);
fa16b376
DW
37}
38
39struct scrub_inode_ctx {
40 struct ptcounter *icount;
41 bool moveon;
42};
43
6c05cc5d
DW
44/* Report a filesystem error that the vfs fed us on close. */
45static void
46xfs_scrub_inode_vfs_error(
47 struct scrub_ctx *ctx,
4cca629d 48 struct xfs_bulkstat *bstat)
6c05cc5d
DW
49{
50 char descr[DESCR_BUFSZ];
6c05cc5d
DW
51 int old_errno = errno;
52
15589f0a
DW
53 scrub_render_ino_descr(ctx, descr, DESCR_BUFSZ, bstat->bs_ino,
54 bstat->bs_gen, NULL);
6c05cc5d
DW
55 errno = old_errno;
56 str_errno(ctx, descr);
57}
58
fa16b376
DW
59/* Verify the contents, xattrs, and extent maps of an inode. */
60static int
61xfs_scrub_inode(
62 struct scrub_ctx *ctx,
63 struct xfs_handle *handle,
4cca629d 64 struct xfs_bulkstat *bstat,
fa16b376
DW
65 void *arg)
66{
ee310b0c 67 struct xfs_action_list alist;
fa16b376
DW
68 struct scrub_inode_ctx *ictx = arg;
69 struct ptcounter *icount = ictx->icount;
ee310b0c 70 xfs_agnumber_t agno;
fa16b376
DW
71 bool moveon = true;
72 int fd = -1;
6c05cc5d 73 int error;
fa16b376 74
ee310b0c 75 xfs_action_list_init(&alist);
a749451c 76 agno = cvt_ino_to_agno(&ctx->mnt, bstat->bs_ino);
fa16b376
DW
77 background_sleep();
78
79 /* Try to open the inode to pin it. */
80 if (S_ISREG(bstat->bs_mode)) {
59f79e0a 81 fd = scrub_open_handle(handle);
fa16b376
DW
82 /* Stale inode means we scan the whole cluster again. */
83 if (fd < 0 && errno == ESTALE)
84 return ESTALE;
85 }
86
87 /* Scrub the inode. */
ee310b0c
DW
88 moveon = xfs_scrub_fd(ctx, xfs_scrub_inode_fields, bstat, &alist);
89 if (!moveon)
90 goto out;
91
92 moveon = xfs_action_list_process_or_defer(ctx, agno, &alist);
fa16b376
DW
93 if (!moveon)
94 goto out;
95
96 /* Scrub all block mappings. */
ee310b0c 97 moveon = xfs_scrub_fd(ctx, xfs_scrub_data_fork, bstat, &alist);
fa16b376
DW
98 if (!moveon)
99 goto out;
ee310b0c 100 moveon = xfs_scrub_fd(ctx, xfs_scrub_attr_fork, bstat, &alist);
fa16b376
DW
101 if (!moveon)
102 goto out;
ee310b0c
DW
103 moveon = xfs_scrub_fd(ctx, xfs_scrub_cow_fork, bstat, &alist);
104 if (!moveon)
105 goto out;
106
107 moveon = xfs_action_list_process_or_defer(ctx, agno, &alist);
fa16b376
DW
108 if (!moveon)
109 goto out;
110
111 if (S_ISLNK(bstat->bs_mode)) {
112 /* Check symlink contents. */
991e5a84
DW
113 moveon = xfs_scrub_symlink(ctx, bstat->bs_ino, bstat->bs_gen,
114 &alist);
fa16b376
DW
115 } else if (S_ISDIR(bstat->bs_mode)) {
116 /* Check the directory entries. */
ee310b0c 117 moveon = xfs_scrub_fd(ctx, xfs_scrub_dir, bstat, &alist);
fa16b376
DW
118 }
119 if (!moveon)
120 goto out;
121
122 /* Check all the extended attributes. */
ee310b0c 123 moveon = xfs_scrub_fd(ctx, xfs_scrub_attr, bstat, &alist);
fa16b376
DW
124 if (!moveon)
125 goto out;
126
127 /* Check parent pointers. */
ee310b0c
DW
128 moveon = xfs_scrub_fd(ctx, xfs_scrub_parent, bstat, &alist);
129 if (!moveon)
130 goto out;
131
132 /* Try to repair the file while it's open. */
133 moveon = xfs_action_list_process_or_defer(ctx, agno, &alist);
fa16b376
DW
134 if (!moveon)
135 goto out;
136
137out:
da3dd6c0
DW
138 error = ptcounter_add(icount, 1);
139 if (error) {
140 str_liberror(ctx, error,
141 _("incrementing scanned inode counter"));
142 return false;
143 }
ed60d210 144 progress_add(1);
ee310b0c 145 xfs_action_list_defer(ctx, agno, &alist);
6c05cc5d
DW
146 if (fd >= 0) {
147 error = close(fd);
148 if (error)
149 xfs_scrub_inode_vfs_error(ctx, bstat);
150 }
fa16b376
DW
151 if (!moveon)
152 ictx->moveon = false;
153 return ictx->moveon ? 0 : XFS_ITERATE_INODES_ABORT;
154}
155
156/* Verify all the inodes in a filesystem. */
157bool
158xfs_scan_inodes(
159 struct scrub_ctx *ctx)
160{
161 struct scrub_inode_ctx ictx;
da3dd6c0
DW
162 uint64_t val;
163 int err;
fa16b376
DW
164
165 ictx.moveon = true;
da3dd6c0
DW
166 err = ptcounter_alloc(scrub_nproc(ctx), &ictx.icount);
167 if (err) {
168 str_liberror(ctx, err, _("creating scanned inode counter"));
fa16b376
DW
169 return false;
170 }
171
59f79e0a
DW
172 err = scrub_scan_all_inodes(ctx, xfs_scrub_inode, &ictx);
173 if (err)
fa16b376
DW
174 ictx.moveon = false;
175 if (!ictx.moveon)
176 goto free;
177 xfs_scrub_report_preen_triggers(ctx);
da3dd6c0
DW
178 err = ptcounter_value(ictx.icount, &val);
179 if (err) {
180 str_liberror(ctx, err, _("summing scanned inode counter"));
181 return false;
182 }
183 ctx->inodes_checked = val;
fa16b376
DW
184free:
185 ptcounter_free(ictx.icount);
186 return ictx.moveon;
187}
ed60d210
DW
188
189/* Estimate how much work we're going to do. */
190bool
191xfs_estimate_inodes_work(
192 struct scrub_ctx *ctx,
193 uint64_t *items,
194 unsigned int *nr_threads,
195 int *rshift)
196{
197 *items = ctx->mnt_sv.f_files - ctx->mnt_sv.f_ffree;
198 *nr_threads = scrub_nproc(ctx);
199 *rshift = 0;
200 return true;
201}