1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2017 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
12 #include "libfrog/paths.h"
13 #include "libfrog/fsgeom.h"
14 #include "libfrog/scrub.h"
17 static struct cmdinfo scrub_cmd
;
18 static struct cmdinfo repair_cmd
;
23 const struct xfrog_scrub_descr
*d
;
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"
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"
38 " Known metadata scrub types are:"));
39 for (i
= 0, d
= xfrog_scrubbers
; i
< XFS_SCRUB_TYPE_NR
; i
++, d
++)
40 printf(" %s", d
->name
);
51 struct xfs_scrub_metadata meta
;
52 const struct xfrog_scrub_descr
*sc
;
55 sc
= &xfrog_scrubbers
[type
];
56 memset(&meta
, 0, sizeof(meta
));
59 case XFROG_SCRUB_TYPE_AGHEADER
:
60 case XFROG_SCRUB_TYPE_PERAG
:
61 meta
.sm_agno
= control
;
63 case XFROG_SCRUB_TYPE_INODE
:
64 meta
.sm_ino
= control
;
65 meta
.sm_gen
= control2
;
67 case XFROG_SCRUB_TYPE_NONE
:
68 case XFROG_SCRUB_TYPE_FS
:
69 /* no control parameters */
74 error
= ioctl(fd
, XFS_IOC_SCRUB_METADATA
, &meta
);
77 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
)
78 printf(_("Corruption detected.\n"));
79 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_PREEN
)
80 printf(_("Optimization possible.\n"));
81 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_XFAIL
)
82 printf(_("Cross-referencing failed.\n"));
83 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_XCORRUPT
)
84 printf(_("Corruption detected during cross-referencing.\n"));
85 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_INCOMPLETE
)
86 printf(_("Scan was not complete.\n"));
93 struct cmdinfo
*cmdinfo
,
94 void (*fn
)(int, int, uint64_t, uint32_t))
100 uint32_t control2
= 0;
101 const struct xfrog_scrub_descr
*d
= NULL
;
103 while ((c
= getopt(argc
, argv
, "")) != EOF
) {
107 return command_usage(cmdinfo
);
110 if (optind
> argc
- 1) {
112 return command_usage(cmdinfo
);
115 for (i
= 0, d
= xfrog_scrubbers
; i
< XFS_SCRUB_TYPE_NR
; i
++, d
++) {
116 if (strcmp(d
->name
, argv
[optind
]) == 0) {
122 printf(_("Unknown type '%s'.\n"), argv
[optind
]);
124 return command_usage(cmdinfo
);
129 case XFROG_SCRUB_TYPE_INODE
:
130 if (optind
== argc
) {
133 } else if (optind
== argc
- 2) {
134 control
= strtoull(argv
[optind
], &p
, 0);
137 _("Bad inode number '%s'.\n"),
140 return command_usage(cmdinfo
);
142 control2
= strtoul(argv
[optind
+ 1], &p
, 0);
145 _("Bad generation number '%s'.\n"),
148 return command_usage(cmdinfo
);
152 _("Must specify inode number and generation.\n"));
154 return command_usage(cmdinfo
);
157 case XFROG_SCRUB_TYPE_AGHEADER
:
158 case XFROG_SCRUB_TYPE_PERAG
:
159 if (optind
!= argc
- 1) {
161 _("Must specify one AG number.\n"));
163 return command_usage(cmdinfo
);
165 control
= strtoul(argv
[optind
], &p
, 0);
168 _("Bad AG number '%s'.\n"), argv
[optind
]);
170 return command_usage(cmdinfo
);
173 case XFROG_SCRUB_TYPE_FS
:
174 case XFROG_SCRUB_TYPE_NONE
:
175 if (optind
!= argc
) {
177 _("No parameters allowed.\n"));
179 return command_usage(cmdinfo
);
186 fn(file
->fd
, type
, control
, control2
);
196 return parse_args(argc
, argv
, &scrub_cmd
, scrub_ioctl
);
202 scrub_cmd
.name
= "scrub";
203 scrub_cmd
.altname
= "sc";
204 scrub_cmd
.cfunc
= scrub_f
;
205 scrub_cmd
.argmin
= 1;
206 scrub_cmd
.argmax
= -1;
207 scrub_cmd
.flags
= CMD_NOMAP_OK
;
208 scrub_cmd
.args
= _("type [agno|ino gen]");
209 scrub_cmd
.oneline
= _("scrubs filesystem metadata");
210 scrub_cmd
.help
= scrub_help
;
212 add_command(&scrub_cmd
);
218 const struct xfrog_scrub_descr
*d
;
223 " Repairs a piece of XFS filesystem metadata. The first argument is the type\n"
224 " of metadata to examine. Allocation group metadata types take one AG number\n"
225 " as the second parameter. Inode metadata types act on the currently open file\n"
226 " or (optionally) take an inode number and generation number to act upon as\n"
227 " the second and third parameters.\n"
230 " 'repair inobt 3' - repairs the inode btree in AG 3.\n"
231 " 'repair bmapbtd 128 13525' - repairs the extent map of inode 128 gen 13525.\n"
233 " Known metadata repairs types are:"));
234 for (i
= 0, d
= xfrog_scrubbers
; i
< XFS_SCRUB_TYPE_NR
; i
++, d
++)
235 printf(" %s", d
->name
);
246 struct xfs_scrub_metadata meta
;
247 const struct xfrog_scrub_descr
*sc
;
250 sc
= &xfrog_scrubbers
[type
];
251 memset(&meta
, 0, sizeof(meta
));
254 case XFROG_SCRUB_TYPE_AGHEADER
:
255 case XFROG_SCRUB_TYPE_PERAG
:
256 meta
.sm_agno
= control
;
258 case XFROG_SCRUB_TYPE_INODE
:
259 meta
.sm_ino
= control
;
260 meta
.sm_gen
= control2
;
262 case XFROG_SCRUB_TYPE_NONE
:
263 case XFROG_SCRUB_TYPE_FS
:
264 /* no control parameters */
267 meta
.sm_flags
= XFS_SCRUB_IFLAG_REPAIR
;
269 error
= ioctl(fd
, XFS_IOC_SCRUB_METADATA
, &meta
);
272 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_CORRUPT
)
273 printf(_("Corruption remains.\n"));
274 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_PREEN
)
275 printf(_("Optimization possible.\n"));
276 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_XFAIL
)
277 printf(_("Cross-referencing failed.\n"));
278 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_XCORRUPT
)
279 printf(_("Corruption still detected during cross-referencing.\n"));
280 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_INCOMPLETE
)
281 printf(_("Repair was not complete.\n"));
282 if (meta
.sm_flags
& XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED
)
283 printf(_("Metadata did not need repair or optimization.\n"));
291 return parse_args(argc
, argv
, &repair_cmd
, repair_ioctl
);
299 repair_cmd
.name
= "repair";
300 repair_cmd
.altname
= "fix";
301 repair_cmd
.cfunc
= repair_f
;
302 repair_cmd
.argmin
= 1;
303 repair_cmd
.argmax
= -1;
304 repair_cmd
.flags
= CMD_NOMAP_OK
;
305 repair_cmd
.args
= _("type [agno|ino gen]");
306 repair_cmd
.oneline
= _("repairs filesystem metadata");
307 repair_cmd
.help
= repair_help
;
309 add_command(&repair_cmd
);