]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/scrub.c
xfs: convert to new timestamp accessors
[thirdparty/xfsprogs-dev.git] / io / scrub.c
CommitLineData
959ef981 1// SPDX-License-Identifier: GPL-2.0
813c67c7
DW
2/*
3 * Copyright (C) 2017 Oracle. All Rights Reserved.
813c67c7 4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
813c67c7
DW
5 */
6
7#include <sys/uio.h>
8#include <xfs/xfs.h>
9#include "command.h"
10#include "input.h"
11#include "init.h"
42b4c8e8 12#include "libfrog/paths.h"
5ef3b66a
DW
13#include "libfrog/fsgeom.h"
14#include "libfrog/scrub.h"
813c67c7
DW
15#include "io.h"
16
17static struct cmdinfo scrub_cmd;
bec810e8 18static struct cmdinfo repair_cmd;
813c67c7 19
813c67c7
DW
20static void
21scrub_help(void)
22{
5ef3b66a 23 const struct xfrog_scrub_descr *d;
813c67c7
DW
24 int i;
25
26 printf(_(
27"\n"
28" Scrubs a piece of XFS filesystem metadata. The first argument is the type\n"
29" of metadata to examine. Allocation group metadata types take one AG number\n"
30" as the second parameter. Inode metadata types act on the currently open file\n"
31" or (optionally) take an inode number and generation number to act upon as\n"
32" the second and third parameters.\n"
33"\n"
34" Example:\n"
35" 'scrub inobt 3' - scrub the inode btree in AG 3.\n"
36" 'scrub bmapbtd 128 13525' - scrubs the extent map of inode 128 gen 13525.\n"
37"\n"
38" Known metadata scrub types are:"));
5ef3b66a 39 for (i = 0, d = xfrog_scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
813c67c7
DW
40 printf(" %s", d->name);
41 printf("\n");
42}
43
99a0612b
DW
44static bool
45parse_inode(
46 int argc,
47 char **argv,
48 int optind,
49 __u64 *ino,
50 __u32 *gen)
51{
52 char *p;
53 unsigned long long control;
54 unsigned long control2;
55
56 if (optind == argc) {
57 *ino = 0;
58 *gen = 0;
59 return true;
60 }
61
62 if (optind != argc - 2) {
63 fprintf(stderr,
64 _("Must specify inode number and generation.\n"));
65 return false;
66 }
67
68 control = strtoull(argv[optind], &p, 0);
69 if (*p != '\0') {
70 fprintf(stderr, _("Bad inode number '%s'.\n"),
71 argv[optind]);
72 return false;
73 }
74 control2 = strtoul(argv[optind + 1], &p, 0);
75 if (*p != '\0') {
76 fprintf(stderr, _("Bad generation number '%s'.\n"),
77 argv[optind + 1]);
78 return false;
79 }
80
81 *ino = control;
82 *gen = control2;
83 return true;
84}
85
86static bool
87parse_agno(
88 int argc,
89 char **argv,
90 int optind,
91 __u32 *agno)
92{
93 char *p;
94 unsigned long control;
95
96 if (optind != argc - 1) {
97 fprintf(stderr, _("Must specify one AG number.\n"));
98 return false;
99 }
100
101 control = strtoul(argv[optind], &p, 0);
102 if (*p != '\0') {
103 fprintf(stderr, _("Bad AG number '%s'.\n"), argv[optind]);
104 return false;
105 }
106
107 *agno = control;
108 return true;
109}
110
111static bool
112parse_none(
113 int argc,
114 int optind)
115{
116 if (optind != argc) {
117 fprintf(stderr, _("No parameters allowed.\n"));
118 return false;
119 }
120
121 /* no control parameters */
122 return true;
123}
124
813c67c7
DW
125static int
126parse_args(
127 int argc,
128 char **argv,
4c91ffcf
DW
129 const struct cmdinfo *cmdinfo,
130 struct xfs_scrub_metadata *meta)
813c67c7 131{
813c67c7
DW
132 int type = -1;
133 int i, c;
9de9b740 134 uint32_t flags = 0;
5ef3b66a 135 const struct xfrog_scrub_descr *d = NULL;
813c67c7 136
4c91ffcf 137 memset(meta, 0, sizeof(struct xfs_scrub_metadata));
9de9b740 138 while ((c = getopt(argc, argv, "R")) != EOF) {
813c67c7 139 switch (c) {
9de9b740
DW
140 case 'R':
141 flags |= XFS_SCRUB_IFLAG_FORCE_REBUILD;
142 break;
813c67c7 143 default:
1067f3cd 144 exitcode = 1;
813c67c7
DW
145 return command_usage(cmdinfo);
146 }
147 }
1067f3cd
DW
148 if (optind > argc - 1) {
149 exitcode = 1;
813c67c7 150 return command_usage(cmdinfo);
1067f3cd 151 }
813c67c7 152
5ef3b66a 153 for (i = 0, d = xfrog_scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++) {
813c67c7
DW
154 if (strcmp(d->name, argv[optind]) == 0) {
155 type = i;
156 break;
157 }
158 }
813c67c7
DW
159 if (type < 0) {
160 printf(_("Unknown type '%s'.\n"), argv[optind]);
1067f3cd 161 exitcode = 1;
813c67c7
DW
162 return command_usage(cmdinfo);
163 }
7856ed05 164 optind++;
813c67c7 165
4c91ffcf 166 meta->sm_type = type;
9de9b740 167 meta->sm_flags = flags;
4c91ffcf 168
813c67c7 169 switch (d->type) {
5ef3b66a 170 case XFROG_SCRUB_TYPE_INODE:
99a0612b
DW
171 if (!parse_inode(argc, argv, optind, &meta->sm_ino,
172 &meta->sm_gen)) {
1067f3cd
DW
173 exitcode = 1;
174 return command_usage(cmdinfo);
813c67c7
DW
175 }
176 break;
5ef3b66a
DW
177 case XFROG_SCRUB_TYPE_AGHEADER:
178 case XFROG_SCRUB_TYPE_PERAG:
99a0612b 179 if (!parse_agno(argc, argv, optind, &meta->sm_agno)) {
1067f3cd
DW
180 exitcode = 1;
181 return command_usage(cmdinfo);
813c67c7
DW
182 }
183 break;
5ef3b66a
DW
184 case XFROG_SCRUB_TYPE_FS:
185 case XFROG_SCRUB_TYPE_NONE:
99a0612b 186 if (!parse_none(argc, optind)) {
1067f3cd
DW
187 exitcode = 1;
188 return command_usage(cmdinfo);
813c67c7
DW
189 }
190 break;
191 default:
192 ASSERT(0);
193 break;
194 }
813c67c7
DW
195 return 0;
196}
197
198static int
199scrub_f(
200 int argc,
201 char **argv)
202{
4c91ffcf
DW
203 struct xfs_scrub_metadata meta;
204 int error;
205
206 error = parse_args(argc, argv, &scrub_cmd, &meta);
207 if (error)
208 return error;
209
210 error = ioctl(file->fd, XFS_IOC_SCRUB_METADATA, &meta);
211 if (error)
212 perror("scrub");
213 if (meta.sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
214 printf(_("Corruption detected.\n"));
215 if (meta.sm_flags & XFS_SCRUB_OFLAG_PREEN)
216 printf(_("Optimization possible.\n"));
217 if (meta.sm_flags & XFS_SCRUB_OFLAG_XFAIL)
218 printf(_("Cross-referencing failed.\n"));
219 if (meta.sm_flags & XFS_SCRUB_OFLAG_XCORRUPT)
220 printf(_("Corruption detected during cross-referencing.\n"));
221 if (meta.sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
222 printf(_("Scan was not complete.\n"));
223 return 0;
813c67c7
DW
224}
225
226void
227scrub_init(void)
228{
229 scrub_cmd.name = "scrub";
230 scrub_cmd.altname = "sc";
231 scrub_cmd.cfunc = scrub_f;
232 scrub_cmd.argmin = 1;
233 scrub_cmd.argmax = -1;
234 scrub_cmd.flags = CMD_NOMAP_OK;
235 scrub_cmd.args = _("type [agno|ino gen]");
236 scrub_cmd.oneline = _("scrubs filesystem metadata");
237 scrub_cmd.help = scrub_help;
238
239 add_command(&scrub_cmd);
240}
bec810e8
DW
241
242static void
243repair_help(void)
244{
5ef3b66a 245 const struct xfrog_scrub_descr *d;
bec810e8
DW
246 int i;
247
248 printf(_(
249"\n"
250" Repairs a piece of XFS filesystem metadata. The first argument is the type\n"
251" of metadata to examine. Allocation group metadata types take one AG number\n"
252" as the second parameter. Inode metadata types act on the currently open file\n"
253" or (optionally) take an inode number and generation number to act upon as\n"
254" the second and third parameters.\n"
255"\n"
9de9b740
DW
256" Flags are -R to force rebuilding metadata.\n"
257"\n"
bec810e8
DW
258" Example:\n"
259" 'repair inobt 3' - repairs the inode btree in AG 3.\n"
260" 'repair bmapbtd 128 13525' - repairs the extent map of inode 128 gen 13525.\n"
261"\n"
9de9b740 262" Known metadata repair types are:"));
5ef3b66a 263 for (i = 0, d = xfrog_scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
bec810e8
DW
264 printf(" %s", d->name);
265 printf("\n");
266}
267
4c91ffcf
DW
268static int
269repair_f(
270 int argc,
271 char **argv)
bec810e8
DW
272{
273 struct xfs_scrub_metadata meta;
bec810e8
DW
274 int error;
275
4c91ffcf
DW
276 error = parse_args(argc, argv, &repair_cmd, &meta);
277 if (error)
278 return error;
279 meta.sm_flags |= XFS_SCRUB_IFLAG_REPAIR;
bec810e8 280
4c91ffcf 281 error = ioctl(file->fd, XFS_IOC_SCRUB_METADATA, &meta);
bec810e8 282 if (error)
f1572219 283 perror("repair");
bec810e8
DW
284 if (meta.sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
285 printf(_("Corruption remains.\n"));
286 if (meta.sm_flags & XFS_SCRUB_OFLAG_PREEN)
287 printf(_("Optimization possible.\n"));
288 if (meta.sm_flags & XFS_SCRUB_OFLAG_XFAIL)
289 printf(_("Cross-referencing failed.\n"));
290 if (meta.sm_flags & XFS_SCRUB_OFLAG_XCORRUPT)
291 printf(_("Corruption still detected during cross-referencing.\n"));
292 if (meta.sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
293 printf(_("Repair was not complete.\n"));
294 if (meta.sm_flags & XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED)
295 printf(_("Metadata did not need repair or optimization.\n"));
4c91ffcf 296 return 0;
bec810e8
DW
297}
298
299void
300repair_init(void)
301{
302 if (!expert)
303 return;
304 repair_cmd.name = "repair";
305 repair_cmd.altname = "fix";
306 repair_cmd.cfunc = repair_f;
307 repair_cmd.argmin = 1;
308 repair_cmd.argmax = -1;
309 repair_cmd.flags = CMD_NOMAP_OK;
310 repair_cmd.args = _("type [agno|ino gen]");
311 repair_cmd.oneline = _("repairs filesystem metadata");
312 repair_cmd.help = repair_help;
313
314 add_command(&repair_cmd);
315}