#include "input.h"
#include "init.h"
#include "libfrog/paths.h"
+#include "libfrog/fsgeom.h"
+#include "libfrog/scrub.h"
#include "io.h"
static struct cmdinfo scrub_cmd;
static struct cmdinfo repair_cmd;
-/* Type info and names for the scrub types. */
-enum scrub_type {
- ST_NONE, /* disabled */
- ST_PERAG, /* per-AG metadata */
- ST_FS, /* per-FS metadata */
- ST_INODE, /* per-inode metadata */
-};
-
-struct scrub_descr {
- const char *name;
- enum scrub_type type;
-};
-
-static const struct scrub_descr scrubbers[XFS_SCRUB_TYPE_NR] = {
- [XFS_SCRUB_TYPE_PROBE] = {"probe", ST_NONE},
- [XFS_SCRUB_TYPE_SB] = {"sb", ST_PERAG},
- [XFS_SCRUB_TYPE_AGF] = {"agf", ST_PERAG},
- [XFS_SCRUB_TYPE_AGFL] = {"agfl", ST_PERAG},
- [XFS_SCRUB_TYPE_AGI] = {"agi", ST_PERAG},
- [XFS_SCRUB_TYPE_BNOBT] = {"bnobt", ST_PERAG},
- [XFS_SCRUB_TYPE_CNTBT] = {"cntbt", ST_PERAG},
- [XFS_SCRUB_TYPE_INOBT] = {"inobt", ST_PERAG},
- [XFS_SCRUB_TYPE_FINOBT] = {"finobt", ST_PERAG},
- [XFS_SCRUB_TYPE_RMAPBT] = {"rmapbt", ST_PERAG},
- [XFS_SCRUB_TYPE_REFCNTBT] = {"refcountbt", ST_PERAG},
- [XFS_SCRUB_TYPE_INODE] = {"inode", ST_INODE},
- [XFS_SCRUB_TYPE_BMBTD] = {"bmapbtd", ST_INODE},
- [XFS_SCRUB_TYPE_BMBTA] = {"bmapbta", ST_INODE},
- [XFS_SCRUB_TYPE_BMBTC] = {"bmapbtc", ST_INODE},
- [XFS_SCRUB_TYPE_DIR] = {"directory", ST_INODE},
- [XFS_SCRUB_TYPE_XATTR] = {"xattr", ST_INODE},
- [XFS_SCRUB_TYPE_SYMLINK] = {"symlink", ST_INODE},
- [XFS_SCRUB_TYPE_PARENT] = {"parent", ST_INODE},
- [XFS_SCRUB_TYPE_RTBITMAP] = {"rtbitmap", ST_FS},
- [XFS_SCRUB_TYPE_RTSUM] = {"rtsummary", ST_FS},
- [XFS_SCRUB_TYPE_UQUOTA] = {"usrquota", ST_FS},
- [XFS_SCRUB_TYPE_GQUOTA] = {"grpquota", ST_FS},
- [XFS_SCRUB_TYPE_PQUOTA] = {"prjquota", ST_FS},
-};
-
static void
scrub_help(void)
{
- const struct scrub_descr *d;
+ const struct xfrog_scrub_descr *d;
int i;
printf(_(
" 'scrub bmapbtd 128 13525' - scrubs the extent map of inode 128 gen 13525.\n"
"\n"
" Known metadata scrub types are:"));
- for (i = 0, d = scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
+ for (i = 0, d = xfrog_scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
printf(" %s", d->name);
printf("\n");
}
uint32_t control2)
{
struct xfs_scrub_metadata meta;
- const struct scrub_descr *sc;
+ const struct xfrog_scrub_descr *sc;
int error;
- sc = &scrubbers[type];
+ sc = &xfrog_scrubbers[type];
memset(&meta, 0, sizeof(meta));
meta.sm_type = type;
switch (sc->type) {
- case ST_PERAG:
+ case XFROG_SCRUB_TYPE_AGHEADER:
+ case XFROG_SCRUB_TYPE_PERAG:
meta.sm_agno = control;
break;
- case ST_INODE:
+ case XFROG_SCRUB_TYPE_INODE:
meta.sm_ino = control;
meta.sm_gen = control2;
break;
- case ST_NONE:
- case ST_FS:
+ case XFROG_SCRUB_TYPE_NONE:
+ case XFROG_SCRUB_TYPE_FS:
/* no control parameters */
break;
}
int i, c;
uint64_t control = 0;
uint32_t control2 = 0;
- const struct scrub_descr *d = NULL;
+ const struct xfrog_scrub_descr *d = NULL;
while ((c = getopt(argc, argv, "")) != EOF) {
switch (c) {
if (optind > argc - 1)
return command_usage(cmdinfo);
- for (i = 0, d = scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++) {
+ for (i = 0, d = xfrog_scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++) {
if (strcmp(d->name, argv[optind]) == 0) {
type = i;
break;
optind++;
switch (d->type) {
- case ST_INODE:
+ case XFROG_SCRUB_TYPE_INODE:
if (optind == argc) {
control = 0;
control2 = 0;
return 0;
}
break;
- case ST_PERAG:
+ case XFROG_SCRUB_TYPE_AGHEADER:
+ case XFROG_SCRUB_TYPE_PERAG:
if (optind != argc - 1) {
fprintf(stderr,
_("Must specify one AG number.\n"));
return 0;
}
break;
- case ST_FS:
- case ST_NONE:
+ case XFROG_SCRUB_TYPE_FS:
+ case XFROG_SCRUB_TYPE_NONE:
if (optind != argc) {
fprintf(stderr,
_("No parameters allowed.\n"));
static void
repair_help(void)
{
- const struct scrub_descr *d;
+ const struct xfrog_scrub_descr *d;
int i;
printf(_(
" 'repair bmapbtd 128 13525' - repairs the extent map of inode 128 gen 13525.\n"
"\n"
" Known metadata repairs types are:"));
- for (i = 0, d = scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
+ for (i = 0, d = xfrog_scrubbers; i < XFS_SCRUB_TYPE_NR; i++, d++)
printf(" %s", d->name);
printf("\n");
}
uint32_t control2)
{
struct xfs_scrub_metadata meta;
- const struct scrub_descr *sc;
+ const struct xfrog_scrub_descr *sc;
int error;
- sc = &scrubbers[type];
+ sc = &xfrog_scrubbers[type];
memset(&meta, 0, sizeof(meta));
meta.sm_type = type;
switch (sc->type) {
- case ST_PERAG:
+ case XFROG_SCRUB_TYPE_AGHEADER:
+ case XFROG_SCRUB_TYPE_PERAG:
meta.sm_agno = control;
break;
- case ST_INODE:
+ case XFROG_SCRUB_TYPE_INODE:
meta.sm_ino = control;
meta.sm_gen = control2;
break;
- case ST_NONE:
- case ST_FS:
+ case XFROG_SCRUB_TYPE_NONE:
+ case XFROG_SCRUB_TYPE_FS:
/* no control parameters */
break;
}
projects.c \
ptvar.c \
radix-tree.c \
+scrub.c \
topology.c \
util.c \
workqueue.c
projects.h \
ptvar.h \
radix-tree.h \
+scrub.h \
topology.h \
workqueue.h
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 Oracle, Inc.
+ * All Rights Reserved.
+ */
+#include "xfs.h"
+#include "fsgeom.h"
+#include "scrub.h"
+
+/* These must correspond to XFS_SCRUB_TYPE_ */
+const struct xfrog_scrub_descr xfrog_scrubbers[XFS_SCRUB_TYPE_NR] = {
+ [XFS_SCRUB_TYPE_PROBE] = {
+ .name = "probe",
+ .descr = "metadata",
+ .type = XFROG_SCRUB_TYPE_NONE,
+ },
+ [XFS_SCRUB_TYPE_SB] = {
+ .name = "sb",
+ .descr = "superblock",
+ .type = XFROG_SCRUB_TYPE_AGHEADER,
+ },
+ [XFS_SCRUB_TYPE_AGF] = {
+ .name = "agf",
+ .descr = "free space header",
+ .type = XFROG_SCRUB_TYPE_AGHEADER,
+ },
+ [XFS_SCRUB_TYPE_AGFL] = {
+ .name = "agfl",
+ .descr = "free list",
+ .type = XFROG_SCRUB_TYPE_AGHEADER,
+ },
+ [XFS_SCRUB_TYPE_AGI] = {
+ .name = "agi",
+ .descr = "inode header",
+ .type = XFROG_SCRUB_TYPE_AGHEADER,
+ },
+ [XFS_SCRUB_TYPE_BNOBT] = {
+ .name = "bnobt",
+ .descr = "freesp by block btree",
+ .type = XFROG_SCRUB_TYPE_PERAG,
+ },
+ [XFS_SCRUB_TYPE_CNTBT] = {
+ .name = "cntbt",
+ .descr = "freesp by length btree",
+ .type = XFROG_SCRUB_TYPE_PERAG,
+ },
+ [XFS_SCRUB_TYPE_INOBT] = {
+ .name = "inobt",
+ .descr = "inode btree",
+ .type = XFROG_SCRUB_TYPE_PERAG,
+ },
+ [XFS_SCRUB_TYPE_FINOBT] = {
+ .name = "finobt",
+ .descr = "free inode btree",
+ .type = XFROG_SCRUB_TYPE_PERAG,
+ },
+ [XFS_SCRUB_TYPE_RMAPBT] = {
+ .name = "rmapbt",
+ .descr = "reverse mapping btree",
+ .type = XFROG_SCRUB_TYPE_PERAG,
+ },
+ [XFS_SCRUB_TYPE_REFCNTBT] = {
+ .name = "refcountbt",
+ .descr = "reference count btree",
+ .type = XFROG_SCRUB_TYPE_PERAG,
+ },
+ [XFS_SCRUB_TYPE_INODE] = {
+ .name = "inode",
+ .descr = "inode record",
+ .type = XFROG_SCRUB_TYPE_INODE,
+ },
+ [XFS_SCRUB_TYPE_BMBTD] = {
+ .name = "bmapbtd",
+ .descr = "data block map",
+ .type = XFROG_SCRUB_TYPE_INODE,
+ },
+ [XFS_SCRUB_TYPE_BMBTA] = {
+ .name = "bmapbta",
+ .descr = "attr block map",
+ .type = XFROG_SCRUB_TYPE_INODE,
+ },
+ [XFS_SCRUB_TYPE_BMBTC] = {
+ .name = "bmapbtc",
+ .descr = "CoW block map",
+ .type = XFROG_SCRUB_TYPE_INODE,
+ },
+ [XFS_SCRUB_TYPE_DIR] = {
+ .name = "directory",
+ .descr = "directory entries",
+ .type = XFROG_SCRUB_TYPE_INODE,
+ },
+ [XFS_SCRUB_TYPE_XATTR] = {
+ .name = "xattr",
+ .descr = "extended attributes",
+ .type = XFROG_SCRUB_TYPE_INODE,
+ },
+ [XFS_SCRUB_TYPE_SYMLINK] = {
+ .name = "symlink",
+ .descr = "symbolic link",
+ .type = XFROG_SCRUB_TYPE_INODE,
+ },
+ [XFS_SCRUB_TYPE_PARENT] = {
+ .name = "parent",
+ .descr = "parent pointer",
+ .type = XFROG_SCRUB_TYPE_INODE,
+ },
+ [XFS_SCRUB_TYPE_RTBITMAP] = {
+ .name = "rtbitmap",
+ .descr = "realtime bitmap",
+ .type = XFROG_SCRUB_TYPE_FS,
+ },
+ [XFS_SCRUB_TYPE_RTSUM] = {
+ .name = "rtsummary",
+ .descr = "realtime summary",
+ .type = XFROG_SCRUB_TYPE_FS,
+ },
+ [XFS_SCRUB_TYPE_UQUOTA] = {
+ .name = "usrquota",
+ .descr = "user quotas",
+ .type = XFROG_SCRUB_TYPE_FS,
+ },
+ [XFS_SCRUB_TYPE_GQUOTA] = {
+ .name = "grpquota",
+ .descr = "group quotas",
+ .type = XFROG_SCRUB_TYPE_FS,
+ },
+ [XFS_SCRUB_TYPE_PQUOTA] = {
+ .name = "prjquota",
+ .descr = "project quotas",
+ .type = XFROG_SCRUB_TYPE_FS,
+ },
+};
+
+int
+xfrog_scrub_metadata(
+ struct xfs_fd *xfd,
+ struct xfs_scrub_metadata *meta)
+{
+ return ioctl(xfd->fd, XFS_IOC_SCRUB_METADATA, meta);
+}
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2019 Oracle, Inc.
+ * All Rights Reserved.
+ */
+#ifndef __LIBFROG_SCRUB_H__
+#define __LIBFROG_SCRUB_H__
+
+/* Type info and names for the scrub types. */
+enum xfrog_scrub_type {
+ XFROG_SCRUB_TYPE_NONE, /* not metadata */
+ XFROG_SCRUB_TYPE_AGHEADER, /* per-AG header */
+ XFROG_SCRUB_TYPE_PERAG, /* per-AG metadata */
+ XFROG_SCRUB_TYPE_FS, /* per-FS metadata */
+ XFROG_SCRUB_TYPE_INODE, /* per-inode metadata */
+};
+
+/* Catalog of scrub types and names, indexed by XFS_SCRUB_TYPE_* */
+struct xfrog_scrub_descr {
+ const char *name;
+ const char *descr;
+ enum xfrog_scrub_type type;
+};
+
+extern const struct xfrog_scrub_descr xfrog_scrubbers[XFS_SCRUB_TYPE_NR];
+
+int xfrog_scrub_metadata(struct xfs_fd *xfd, struct xfs_scrub_metadata *meta);
+
+#endif /* __LIBFROG_SCRUB_H__ */
#include <sys/statvfs.h>
#include "list.h"
#include "libfrog/paths.h"
+#include "libfrog/fsgeom.h"
+#include "libfrog/scrub.h"
#include "xfs_scrub.h"
#include "common.h"
#include "progress.h"
/* Online scrub and repair wrappers. */
-/* Type info and names for the scrub types. */
-enum scrub_type {
- ST_NONE, /* disabled */
- ST_AGHEADER, /* per-AG header */
- ST_PERAG, /* per-AG metadata */
- ST_FS, /* per-FS metadata */
- ST_INODE, /* per-inode metadata */
-};
-struct scrub_descr {
- const char *name;
- enum scrub_type type;
-};
-
-/* These must correspond to XFS_SCRUB_TYPE_ */
-static const struct scrub_descr scrubbers[XFS_SCRUB_TYPE_NR] = {
- [XFS_SCRUB_TYPE_PROBE] =
- {"metadata", ST_NONE},
- [XFS_SCRUB_TYPE_SB] =
- {"superblock", ST_AGHEADER},
- [XFS_SCRUB_TYPE_AGF] =
- {"free space header", ST_AGHEADER},
- [XFS_SCRUB_TYPE_AGFL] =
- {"free list", ST_AGHEADER},
- [XFS_SCRUB_TYPE_AGI] =
- {"inode header", ST_AGHEADER},
- [XFS_SCRUB_TYPE_BNOBT] =
- {"freesp by block btree", ST_PERAG},
- [XFS_SCRUB_TYPE_CNTBT] =
- {"freesp by length btree", ST_PERAG},
- [XFS_SCRUB_TYPE_INOBT] =
- {"inode btree", ST_PERAG},
- [XFS_SCRUB_TYPE_FINOBT] =
- {"free inode btree", ST_PERAG},
- [XFS_SCRUB_TYPE_RMAPBT] =
- {"reverse mapping btree", ST_PERAG},
- [XFS_SCRUB_TYPE_REFCNTBT] =
- {"reference count btree", ST_PERAG},
- [XFS_SCRUB_TYPE_INODE] =
- {"inode record", ST_INODE},
- [XFS_SCRUB_TYPE_BMBTD] =
- {"data block map", ST_INODE},
- [XFS_SCRUB_TYPE_BMBTA] =
- {"attr block map", ST_INODE},
- [XFS_SCRUB_TYPE_BMBTC] =
- {"CoW block map", ST_INODE},
- [XFS_SCRUB_TYPE_DIR] =
- {"directory entries", ST_INODE},
- [XFS_SCRUB_TYPE_XATTR] =
- {"extended attributes", ST_INODE},
- [XFS_SCRUB_TYPE_SYMLINK] =
- {"symbolic link", ST_INODE},
- [XFS_SCRUB_TYPE_PARENT] =
- {"parent pointer", ST_INODE},
- [XFS_SCRUB_TYPE_RTBITMAP] =
- {"realtime bitmap", ST_FS},
- [XFS_SCRUB_TYPE_RTSUM] =
- {"realtime summary", ST_FS},
- [XFS_SCRUB_TYPE_UQUOTA] =
- {"user quotas", ST_FS},
- [XFS_SCRUB_TYPE_GQUOTA] =
- {"group quotas", ST_FS},
- [XFS_SCRUB_TYPE_PQUOTA] =
- {"project quotas", ST_FS},
-};
-
/* Format a scrub description. */
static void
format_scrub_descr(
char *buf,
size_t buflen,
struct xfs_scrub_metadata *meta,
- const struct scrub_descr *sc)
+ const struct xfrog_scrub_descr *sc)
{
switch (sc->type) {
- case ST_AGHEADER:
- case ST_PERAG:
+ case XFROG_SCRUB_TYPE_AGHEADER:
+ case XFROG_SCRUB_TYPE_PERAG:
snprintf(buf, buflen, _("AG %u %s"), meta->sm_agno,
- _(sc->name));
+ _(sc->descr));
break;
- case ST_INODE:
+ case XFROG_SCRUB_TYPE_INODE:
snprintf(buf, buflen, _("Inode %"PRIu64" %s"),
- (uint64_t)meta->sm_ino, _(sc->name));
+ (uint64_t)meta->sm_ino, _(sc->descr));
break;
- case ST_FS:
- snprintf(buf, buflen, _("%s"), _(sc->name));
+ case XFROG_SCRUB_TYPE_FS:
+ snprintf(buf, buflen, _("%s"), _(sc->descr));
break;
- case ST_NONE:
+ case XFROG_SCRUB_TYPE_NONE:
assert(0);
break;
}
assert(!debug_tweak_on("XFS_SCRUB_NO_KERNEL"));
assert(meta->sm_type < XFS_SCRUB_TYPE_NR);
- format_scrub_descr(buf, DESCR_BUFSZ, meta, &scrubbers[meta->sm_type]);
+ format_scrub_descr(buf, DESCR_BUFSZ, meta,
+ &xfrog_scrubbers[meta->sm_type]);
dbg_printf("check %s flags %xh\n", buf, meta->sm_flags);
retry:
- error = ioctl(ctx->mnt.fd, XFS_IOC_SCRUB_METADATA, meta);
+ error = xfrog_scrub_metadata(&ctx->mnt, meta);
if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR") && !error)
meta->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
if (error) {
ctx->preen_triggers[i] = false;
pthread_mutex_unlock(&ctx->lock);
str_info(ctx, ctx->mntpoint,
-_("Optimizations of %s are possible."), scrubbers[i].name);
+_("Optimizations of %s are possible."), _(xfrog_scrubbers[i].descr));
} else {
pthread_mutex_unlock(&ctx->lock);
}
memset(aitem, 0, sizeof(*aitem));
aitem->type = meta->sm_type;
aitem->flags = meta->sm_flags;
- switch (scrubbers[meta->sm_type].type) {
- case ST_AGHEADER:
- case ST_PERAG:
+ switch (xfrog_scrubbers[meta->sm_type].type) {
+ case XFROG_SCRUB_TYPE_AGHEADER:
+ case XFROG_SCRUB_TYPE_PERAG:
aitem->agno = meta->sm_agno;
break;
- case ST_INODE:
+ case XFROG_SCRUB_TYPE_INODE:
aitem->ino = meta->sm_ino;
aitem->gen = meta->sm_gen;
break;
static bool
xfs_scrub_metadata(
struct scrub_ctx *ctx,
- enum scrub_type scrub_type,
+ enum xfrog_scrub_type scrub_type,
xfs_agnumber_t agno,
struct xfs_action_list *alist)
{
struct xfs_scrub_metadata meta = {0};
- const struct scrub_descr *sc;
+ const struct xfrog_scrub_descr *sc;
enum check_outcome fix;
int type;
- sc = scrubbers;
+ sc = xfrog_scrubbers;
for (type = 0; type < XFS_SCRUB_TYPE_NR; type++, sc++) {
if (sc->type != scrub_type)
continue;
xfs_agnumber_t agno,
struct xfs_action_list *alist)
{
- return xfs_scrub_metadata(ctx, ST_AGHEADER, agno, alist);
+ return xfs_scrub_metadata(ctx, XFROG_SCRUB_TYPE_AGHEADER, agno, alist);
}
/* Scrub each AG's metadata btrees. */
xfs_agnumber_t agno,
struct xfs_action_list *alist)
{
- return xfs_scrub_metadata(ctx, ST_PERAG, agno, alist);
+ return xfs_scrub_metadata(ctx, XFROG_SCRUB_TYPE_PERAG, agno, alist);
}
/* Scrub whole-FS metadata btrees. */
struct scrub_ctx *ctx,
struct xfs_action_list *alist)
{
- return xfs_scrub_metadata(ctx, ST_FS, 0, alist);
+ return xfs_scrub_metadata(ctx, XFROG_SCRUB_TYPE_FS, 0, alist);
}
/* How many items do we have to check? */
xfs_scrub_estimate_ag_work(
struct scrub_ctx *ctx)
{
- const struct scrub_descr *sc;
+ const struct xfrog_scrub_descr *sc;
int type;
unsigned int estimate = 0;
- sc = scrubbers;
+ sc = xfrog_scrubbers;
for (type = 0; type < XFS_SCRUB_TYPE_NR; type++, sc++) {
switch (sc->type) {
- case ST_AGHEADER:
- case ST_PERAG:
+ case XFROG_SCRUB_TYPE_AGHEADER:
+ case XFROG_SCRUB_TYPE_PERAG:
estimate += ctx->mnt.fsgeom.agcount;
break;
- case ST_FS:
+ case XFROG_SCRUB_TYPE_FS:
estimate++;
break;
default:
enum check_outcome fix;
assert(type < XFS_SCRUB_TYPE_NR);
- assert(scrubbers[type].type == ST_INODE);
+ assert(xfrog_scrubbers[type].type == XFROG_SCRUB_TYPE_INODE);
meta.sm_type = type;
meta.sm_ino = ino;
meta.sm_type = type;
if (repair)
meta.sm_flags |= XFS_SCRUB_IFLAG_REPAIR;
- error = ioctl(ctx->mnt.fd, XFS_IOC_SCRUB_METADATA, &meta);
+ error = xfrog_scrub_metadata(&ctx->mnt, &meta);
if (!error)
return true;
switch (errno) {
if (debug || verbose)
str_info(ctx, ctx->mntpoint,
_("Kernel %s %s facility not detected."),
- _(scrubbers[type].name),
+ _(xfrog_scrubbers[type].descr),
repair ? _("repair") : _("scrub"));
return false;
case ENOENT:
assert(!debug_tweak_on("XFS_SCRUB_NO_KERNEL"));
meta.sm_type = aitem->type;
meta.sm_flags = aitem->flags | XFS_SCRUB_IFLAG_REPAIR;
- switch (scrubbers[aitem->type].type) {
- case ST_AGHEADER:
- case ST_PERAG:
+ switch (xfrog_scrubbers[aitem->type].type) {
+ case XFROG_SCRUB_TYPE_AGHEADER:
+ case XFROG_SCRUB_TYPE_PERAG:
meta.sm_agno = aitem->agno;
break;
- case ST_INODE:
+ case XFROG_SCRUB_TYPE_INODE:
meta.sm_ino = aitem->ino;
meta.sm_gen = aitem->gen;
break;
return CHECK_RETRY;
memcpy(&oldm, &meta, sizeof(oldm));
- format_scrub_descr(buf, DESCR_BUFSZ, &meta, &scrubbers[meta.sm_type]);
+ format_scrub_descr(buf, DESCR_BUFSZ, &meta,
+ &xfrog_scrubbers[meta.sm_type]);
if (needs_repair(&meta))
str_info(ctx, buf, _("Attempting repair."));
else if (debug || verbose)
str_info(ctx, buf, _("Attempting optimization."));
- error = ioctl(fd, XFS_IOC_SCRUB_METADATA, &meta);
+ error = xfrog_scrub_metadata(&ctx->mnt, &meta);
if (error) {
switch (errno) {
case EDEADLOCK: