]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/phase3.c
xfs_scrub: remove moveon from main program
[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 */
d22f2471
DW
28static int
29scrub_fd(
fa16b376 30 struct scrub_ctx *ctx,
d22f2471 31 int (*fn)(struct scrub_ctx *ctx, uint64_t ino,
83d2c80b 32 uint32_t gen, struct action_list *a),
4cca629d 33 struct xfs_bulkstat *bs,
83d2c80b 34 struct 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;
df024103 41 bool aborted;
fa16b376
DW
42};
43
6c05cc5d
DW
44/* Report a filesystem error that the vfs fed us on close. */
45static void
df024103 46report_close_error(
6c05cc5d 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
df024103 61scrub_inode(
fa16b376
DW
62 struct scrub_ctx *ctx,
63 struct xfs_handle *handle,
4cca629d 64 struct xfs_bulkstat *bstat,
fa16b376
DW
65 void *arg)
66{
83d2c80b 67 struct 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 71 int fd = -1;
6c05cc5d 72 int error;
fa16b376 73
83d2c80b 74 action_list_init(&alist);
a749451c 75 agno = cvt_ino_to_agno(&ctx->mnt, bstat->bs_ino);
fa16b376
DW
76 background_sleep();
77
78 /* Try to open the inode to pin it. */
79 if (S_ISREG(bstat->bs_mode)) {
59f79e0a 80 fd = scrub_open_handle(handle);
fa16b376
DW
81 /* Stale inode means we scan the whole cluster again. */
82 if (fd < 0 && errno == ESTALE)
83 return ESTALE;
84 }
85
86 /* Scrub the inode. */
d22f2471
DW
87 error = scrub_fd(ctx, xfs_scrub_inode_fields, bstat, &alist);
88 if (error)
ee310b0c
DW
89 goto out;
90
83d2c80b
DW
91 error = action_list_process_or_defer(ctx, agno, &alist);
92 if (error)
fa16b376
DW
93 goto out;
94
95 /* Scrub all block mappings. */
d22f2471
DW
96 error = scrub_fd(ctx, xfs_scrub_data_fork, bstat, &alist);
97 if (error)
fa16b376 98 goto out;
d22f2471
DW
99 error = scrub_fd(ctx, xfs_scrub_attr_fork, bstat, &alist);
100 if (error)
fa16b376 101 goto out;
d22f2471
DW
102 error = scrub_fd(ctx, xfs_scrub_cow_fork, bstat, &alist);
103 if (error)
ee310b0c
DW
104 goto out;
105
83d2c80b
DW
106 error = action_list_process_or_defer(ctx, agno, &alist);
107 if (error)
fa16b376
DW
108 goto out;
109
110 if (S_ISLNK(bstat->bs_mode)) {
111 /* Check symlink contents. */
d22f2471 112 error = xfs_scrub_symlink(ctx, bstat->bs_ino, bstat->bs_gen,
991e5a84 113 &alist);
fa16b376
DW
114 } else if (S_ISDIR(bstat->bs_mode)) {
115 /* Check the directory entries. */
d22f2471 116 error = scrub_fd(ctx, xfs_scrub_dir, bstat, &alist);
fa16b376 117 }
d22f2471 118 if (error)
fa16b376
DW
119 goto out;
120
121 /* Check all the extended attributes. */
d22f2471
DW
122 error = scrub_fd(ctx, xfs_scrub_attr, bstat, &alist);
123 if (error)
fa16b376
DW
124 goto out;
125
126 /* Check parent pointers. */
d22f2471
DW
127 error = scrub_fd(ctx, xfs_scrub_parent, bstat, &alist);
128 if (error)
ee310b0c
DW
129 goto out;
130
131 /* Try to repair the file while it's open. */
83d2c80b
DW
132 error = action_list_process_or_defer(ctx, agno, &alist);
133 if (error)
fa16b376
DW
134 goto out;
135
136out:
d22f2471 137 if (error)
df024103
DW
138 ictx->aborted = true;
139
da3dd6c0
DW
140 error = ptcounter_add(icount, 1);
141 if (error) {
142 str_liberror(ctx, error,
143 _("incrementing scanned inode counter"));
df024103 144 ictx->aborted = true;
da3dd6c0 145 }
ed60d210 146 progress_add(1);
83d2c80b 147 action_list_defer(ctx, agno, &alist);
6c05cc5d 148 if (fd >= 0) {
df024103
DW
149 int err2;
150
151 err2 = close(fd);
152 if (err2) {
153 report_close_error(ctx, bstat);
154 ictx->aborted = true;
155 }
6c05cc5d 156 }
df024103
DW
157
158 if (!error && ictx->aborted)
159 error = ECANCELED;
160 return error;
fa16b376
DW
161}
162
163/* Verify all the inodes in a filesystem. */
df024103
DW
164int
165phase3_func(
fa16b376
DW
166 struct scrub_ctx *ctx)
167{
df024103 168 struct scrub_inode_ctx ictx = { NULL };
da3dd6c0
DW
169 uint64_t val;
170 int err;
fa16b376 171
da3dd6c0
DW
172 err = ptcounter_alloc(scrub_nproc(ctx), &ictx.icount);
173 if (err) {
174 str_liberror(ctx, err, _("creating scanned inode counter"));
df024103 175 return err;
fa16b376
DW
176 }
177
df024103
DW
178 err = scrub_scan_all_inodes(ctx, scrub_inode, &ictx);
179 if (!err && ictx.aborted)
180 err = ECANCELED;
59f79e0a 181 if (err)
fa16b376 182 goto free;
df024103 183
fa16b376 184 xfs_scrub_report_preen_triggers(ctx);
da3dd6c0
DW
185 err = ptcounter_value(ictx.icount, &val);
186 if (err) {
187 str_liberror(ctx, err, _("summing scanned inode counter"));
df024103 188 return err;
da3dd6c0 189 }
df024103 190
da3dd6c0 191 ctx->inodes_checked = val;
fa16b376
DW
192free:
193 ptcounter_free(ictx.icount);
df024103 194 return err;
fa16b376 195}
ed60d210 196
df024103
DW
197/* Estimate how much work we're going to do. */
198int
199phase3_estimate(
ed60d210
DW
200 struct scrub_ctx *ctx,
201 uint64_t *items,
202 unsigned int *nr_threads,
203 int *rshift)
204{
205 *items = ctx->mnt_sv.f_files - ctx->mnt_sv.f_ffree;
206 *nr_threads = scrub_nproc(ctx);
207 *rshift = 0;
df024103
DW
208 return 0;
209}