aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-02-02 09:32:46 -0600
committerEric Sandeen <sandeen@redhat.com>2018-02-02 09:32:46 -0600
commite758ad0198760fcb4daaf3560feb7292d314b344 (patch)
treea1109320e293f5502137e6f623237f96db7045f2
parentfd7d73c0c4643496e3cc4f1aedd14689a4d57200 (diff)
downloadxfsprogs-dev-e758ad0198760fcb4daaf3560feb7292d314b344.tar.gz
xfs_scrub: scan filesystem and AG metadata
Scrub the filesystem and per-AG metadata. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--scrub/Makefile1
-rw-r--r--scrub/phase2.c133
-rw-r--r--scrub/xfs_scrub.c1
-rw-r--r--scrub/xfs_scrub.h1
4 files changed, 136 insertions, 0 deletions
diff --git a/scrub/Makefile b/scrub/Makefile
index 915b801f4e..9edc933d84 100644
--- a/scrub/Makefile
+++ b/scrub/Makefile
@@ -32,6 +32,7 @@ filemap.c \
fscounters.c \
inodes.c \
phase1.c \
+phase2.c \
scrub.c \
spacemap.c \
xfs_scrub.c
diff --git a/scrub/phase2.c b/scrub/phase2.c
new file mode 100644
index 0000000000..153ae026b7
--- /dev/null
+++ b/scrub/phase2.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2018 Oracle. All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include "xfs.h"
+#include "path.h"
+#include "workqueue.h"
+#include "xfs_scrub.h"
+#include "common.h"
+#include "scrub.h"
+
+/* Phase 2: Check internal metadata. */
+
+/* Scrub each AG's metadata btrees. */
+static void
+xfs_scan_ag_metadata(
+ struct workqueue *wq,
+ xfs_agnumber_t agno,
+ void *arg)
+{
+ struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
+ bool *pmoveon = arg;
+ bool moveon;
+ char descr[DESCR_BUFSZ];
+
+ snprintf(descr, DESCR_BUFSZ, _("AG %u"), agno);
+
+ /*
+ * First we scrub and fix the AG headers, because we need
+ * them to work well enough to check the AG btrees.
+ */
+ moveon = xfs_scrub_ag_headers(ctx, agno);
+ if (!moveon)
+ goto err;
+
+ /* Now scrub the AG btrees. */
+ moveon = xfs_scrub_ag_metadata(ctx, agno);
+ if (!moveon)
+ goto err;
+
+ return;
+err:
+ *pmoveon = false;
+}
+
+/* Scrub whole-FS metadata btrees. */
+static void
+xfs_scan_fs_metadata(
+ struct workqueue *wq,
+ xfs_agnumber_t agno,
+ void *arg)
+{
+ struct scrub_ctx *ctx = (struct scrub_ctx *)wq->wq_ctx;
+ bool *pmoveon = arg;
+ bool moveon;
+
+ moveon = xfs_scrub_fs_metadata(ctx);
+ if (!moveon)
+ *pmoveon = false;
+}
+
+/* Scan all filesystem metadata. */
+bool
+xfs_scan_metadata(
+ struct scrub_ctx *ctx)
+{
+ struct workqueue wq;
+ xfs_agnumber_t agno;
+ bool moveon = true;
+ int ret;
+
+ ret = workqueue_create(&wq, (struct xfs_mount *)ctx,
+ scrub_nproc_workqueue(ctx));
+ if (ret) {
+ str_error(ctx, ctx->mntpoint, _("Could not create workqueue."));
+ return false;
+ }
+
+ /*
+ * In case we ever use the primary super scrubber to perform fs
+ * upgrades (followed by a full scrub), do that before we launch
+ * anything else.
+ */
+ moveon = xfs_scrub_primary_super(ctx);
+ if (!moveon)
+ return moveon;
+
+ for (agno = 0; moveon && agno < ctx->geo.agcount; agno++) {
+ ret = workqueue_add(&wq, xfs_scan_ag_metadata, agno, &moveon);
+ if (ret) {
+ moveon = false;
+ str_error(ctx, ctx->mntpoint,
+_("Could not queue AG %u scrub work."), agno);
+ goto out;
+ }
+ }
+
+ if (!moveon)
+ goto out;
+
+ ret = workqueue_add(&wq, xfs_scan_fs_metadata, 0, &moveon);
+ if (ret) {
+ moveon = false;
+ str_error(ctx, ctx->mntpoint,
+_("Could not queue filesystem scrub work."));
+ goto out;
+ }
+
+out:
+ workqueue_destroy(&wq);
+ return moveon;
+}
diff --git a/scrub/xfs_scrub.c b/scrub/xfs_scrub.c
index 577e0b2208..4c32dd74a3 100644
--- a/scrub/xfs_scrub.c
+++ b/scrub/xfs_scrub.c
@@ -368,6 +368,7 @@ run_scrub_phases(
},
{
.descr = _("Check internal metadata."),
+ .fn = xfs_scan_metadata,
},
{
.descr = _("Scan all inodes."),
diff --git a/scrub/xfs_scrub.h b/scrub/xfs_scrub.h
index 914490ae54..7802101508 100644
--- a/scrub/xfs_scrub.h
+++ b/scrub/xfs_scrub.h
@@ -94,5 +94,6 @@ struct scrub_ctx {
void xfs_shutdown_fs(struct scrub_ctx *ctx);
bool xfs_cleanup_fs(struct scrub_ctx *ctx);
bool xfs_setup_fs(struct scrub_ctx *ctx);
+bool xfs_scan_metadata(struct scrub_ctx *ctx);
#endif /* XFS_SCRUB_XFS_SCRUB_H_ */