]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/phase3.c
debian/control: remove nonexistent libreadline5-dev build dependency
[thirdparty/xfsprogs-dev.git] / scrub / phase3.c
CommitLineData
fa16b376
DW
1/*
2 * Copyright (C) 2018 Oracle. All Rights Reserved.
3 *
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20#include <stdio.h>
21#include <stdint.h>
22#include <stdbool.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <sys/statvfs.h>
26#include "xfs.h"
27#include "path.h"
28#include "workqueue.h"
29#include "xfs_scrub.h"
30#include "common.h"
31#include "counter.h"
32#include "inodes.h"
ed60d210 33#include "progress.h"
fa16b376
DW
34#include "scrub.h"
35
36/* Phase 3: Scan all inodes. */
37
38/*
39 * Run a per-file metadata scanner. We use the ino/gen interface to
40 * ensure that the inode we're checking matches what the inode scan
41 * told us to look at.
42 */
43static bool
44xfs_scrub_fd(
45 struct scrub_ctx *ctx,
46 bool (*fn)(struct scrub_ctx *, uint64_t,
47 uint32_t, int),
48 struct xfs_bstat *bs)
49{
50 return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt_fd);
51}
52
53struct scrub_inode_ctx {
54 struct ptcounter *icount;
55 bool moveon;
56};
57
58/* Verify the contents, xattrs, and extent maps of an inode. */
59static int
60xfs_scrub_inode(
61 struct scrub_ctx *ctx,
62 struct xfs_handle *handle,
63 struct xfs_bstat *bstat,
64 void *arg)
65{
66 struct scrub_inode_ctx *ictx = arg;
67 struct ptcounter *icount = ictx->icount;
68 bool moveon = true;
69 int fd = -1;
70
71 background_sleep();
72
73 /* Try to open the inode to pin it. */
74 if (S_ISREG(bstat->bs_mode)) {
75 fd = xfs_open_handle(handle);
76 /* Stale inode means we scan the whole cluster again. */
77 if (fd < 0 && errno == ESTALE)
78 return ESTALE;
79 }
80
81 /* Scrub the inode. */
82 moveon = xfs_scrub_fd(ctx, xfs_scrub_inode_fields, bstat);
83 if (!moveon)
84 goto out;
85
86 /* Scrub all block mappings. */
87 moveon = xfs_scrub_fd(ctx, xfs_scrub_data_fork, bstat);
88 if (!moveon)
89 goto out;
90 moveon = xfs_scrub_fd(ctx, xfs_scrub_attr_fork, bstat);
91 if (!moveon)
92 goto out;
93 moveon = xfs_scrub_fd(ctx, xfs_scrub_cow_fork, bstat);
94 if (!moveon)
95 goto out;
96
97 if (S_ISLNK(bstat->bs_mode)) {
98 /* Check symlink contents. */
99 moveon = xfs_scrub_symlink(ctx, bstat->bs_ino,
100 bstat->bs_gen, ctx->mnt_fd);
101 } else if (S_ISDIR(bstat->bs_mode)) {
102 /* Check the directory entries. */
103 moveon = xfs_scrub_fd(ctx, xfs_scrub_dir, bstat);
104 }
105 if (!moveon)
106 goto out;
107
108 /* Check all the extended attributes. */
109 moveon = xfs_scrub_fd(ctx, xfs_scrub_attr, bstat);
110 if (!moveon)
111 goto out;
112
113 /* Check parent pointers. */
114 moveon = xfs_scrub_fd(ctx, xfs_scrub_parent, bstat);
115 if (!moveon)
116 goto out;
117
118out:
119 ptcounter_add(icount, 1);
ed60d210 120 progress_add(1);
fa16b376
DW
121 if (fd >= 0)
122 close(fd);
123 if (!moveon)
124 ictx->moveon = false;
125 return ictx->moveon ? 0 : XFS_ITERATE_INODES_ABORT;
126}
127
128/* Verify all the inodes in a filesystem. */
129bool
130xfs_scan_inodes(
131 struct scrub_ctx *ctx)
132{
133 struct scrub_inode_ctx ictx;
134 bool ret;
135
136 ictx.moveon = true;
137 ictx.icount = ptcounter_init(scrub_nproc(ctx));
138 if (!ictx.icount) {
139 str_error(ctx, ctx->mntpoint, _("Could not create counter."));
140 return false;
141 }
142
143 ret = xfs_scan_all_inodes(ctx, xfs_scrub_inode, &ictx);
144 if (!ret)
145 ictx.moveon = false;
146 if (!ictx.moveon)
147 goto free;
148 xfs_scrub_report_preen_triggers(ctx);
149 ctx->inodes_checked = ptcounter_value(ictx.icount);
150
151free:
152 ptcounter_free(ictx.icount);
153 return ictx.moveon;
154}
ed60d210
DW
155
156/* Estimate how much work we're going to do. */
157bool
158xfs_estimate_inodes_work(
159 struct scrub_ctx *ctx,
160 uint64_t *items,
161 unsigned int *nr_threads,
162 int *rshift)
163{
164 *items = ctx->mnt_sv.f_files - ctx->mnt_sv.f_ffree;
165 *nr_threads = scrub_nproc(ctx);
166 *rshift = 0;
167 return true;
168}