]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_scrub: scan inodes
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 2 Feb 2018 15:32:46 +0000 (09:32 -0600)
committerEric Sandeen <sandeen@redhat.com>
Fri, 2 Feb 2018 15:32:46 +0000 (09:32 -0600)
Scan all the inodes in the system for problems.

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>
scrub/Makefile
scrub/phase3.c [new file with mode: 0644]
scrub/xfs_scrub.c
scrub/xfs_scrub.h

index 30dbe54092787698ed358fac335b42aac2383b55..e0d15d885fc340c71ea58bd724f49d5bdcf27323 100644 (file)
@@ -35,6 +35,7 @@ fscounters.c \
 inodes.c \
 phase1.c \
 phase2.c \
+phase3.c \
 scrub.c \
 spacemap.c \
 xfs_scrub.c
diff --git a/scrub/phase3.c b/scrub/phase3.c
new file mode 100644 (file)
index 0000000..b3fc510
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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 "counter.h"
+#include "inodes.h"
+#include "scrub.h"
+
+/* Phase 3: Scan all inodes. */
+
+/*
+ * Run a per-file metadata scanner.  We use the ino/gen interface to
+ * ensure that the inode we're checking matches what the inode scan
+ * told us to look at.
+ */
+static bool
+xfs_scrub_fd(
+       struct scrub_ctx        *ctx,
+       bool                    (*fn)(struct scrub_ctx *, uint64_t,
+                                     uint32_t, int),
+       struct xfs_bstat        *bs)
+{
+       return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt_fd);
+}
+
+struct scrub_inode_ctx {
+       struct ptcounter        *icount;
+       bool                    moveon;
+};
+
+/* Verify the contents, xattrs, and extent maps of an inode. */
+static int
+xfs_scrub_inode(
+       struct scrub_ctx        *ctx,
+       struct xfs_handle       *handle,
+       struct xfs_bstat        *bstat,
+       void                    *arg)
+{
+       struct scrub_inode_ctx  *ictx = arg;
+       struct ptcounter        *icount = ictx->icount;
+       bool                    moveon = true;
+       int                     fd = -1;
+
+       background_sleep();
+
+       /* Try to open the inode to pin it. */
+       if (S_ISREG(bstat->bs_mode)) {
+               fd = xfs_open_handle(handle);
+               /* Stale inode means we scan the whole cluster again. */
+               if (fd < 0 && errno == ESTALE)
+                       return ESTALE;
+       }
+
+       /* Scrub the inode. */
+       moveon = xfs_scrub_fd(ctx, xfs_scrub_inode_fields, bstat);
+       if (!moveon)
+               goto out;
+
+       /* Scrub all block mappings. */
+       moveon = xfs_scrub_fd(ctx, xfs_scrub_data_fork, bstat);
+       if (!moveon)
+               goto out;
+       moveon = xfs_scrub_fd(ctx, xfs_scrub_attr_fork, bstat);
+       if (!moveon)
+               goto out;
+       moveon = xfs_scrub_fd(ctx, xfs_scrub_cow_fork, bstat);
+       if (!moveon)
+               goto out;
+
+       if (S_ISLNK(bstat->bs_mode)) {
+               /* Check symlink contents. */
+               moveon = xfs_scrub_symlink(ctx, bstat->bs_ino,
+                               bstat->bs_gen, ctx->mnt_fd);
+       } else if (S_ISDIR(bstat->bs_mode)) {
+               /* Check the directory entries. */
+               moveon = xfs_scrub_fd(ctx, xfs_scrub_dir, bstat);
+       }
+       if (!moveon)
+               goto out;
+
+       /* Check all the extended attributes. */
+       moveon = xfs_scrub_fd(ctx, xfs_scrub_attr, bstat);
+       if (!moveon)
+               goto out;
+
+       /* Check parent pointers. */
+       moveon = xfs_scrub_fd(ctx, xfs_scrub_parent, bstat);
+       if (!moveon)
+               goto out;
+
+out:
+       ptcounter_add(icount, 1);
+       if (fd >= 0)
+               close(fd);
+       if (!moveon)
+               ictx->moveon = false;
+       return ictx->moveon ? 0 : XFS_ITERATE_INODES_ABORT;
+}
+
+/* Verify all the inodes in a filesystem. */
+bool
+xfs_scan_inodes(
+       struct scrub_ctx        *ctx)
+{
+       struct scrub_inode_ctx  ictx;
+       bool                    ret;
+
+       ictx.moveon = true;
+       ictx.icount = ptcounter_init(scrub_nproc(ctx));
+       if (!ictx.icount) {
+               str_error(ctx, ctx->mntpoint, _("Could not create counter."));
+               return false;
+       }
+
+       ret = xfs_scan_all_inodes(ctx, xfs_scrub_inode, &ictx);
+       if (!ret)
+               ictx.moveon = false;
+       if (!ictx.moveon)
+               goto free;
+       xfs_scrub_report_preen_triggers(ctx);
+       ctx->inodes_checked = ptcounter_value(ictx.icount);
+
+free:
+       ptcounter_free(ictx.icount);
+       return ictx.moveon;
+}
index 4c32dd74a3f515ffb40f8a9c4e9f0cbf34230984..be809fc81308f1676a302dc892a0e1005da5a6ed 100644 (file)
@@ -372,6 +372,7 @@ run_scrub_phases(
                },
                {
                        .descr = _("Scan all inodes."),
+                       .fn = xfs_scan_inodes,
                },
                {
                        .descr = _("Defer filesystem repairs."),
index 780210150852bc18b3943a47bf1994ef5664e4ad..462b5905f2ad4c74770f991a8fb9add886c27efc 100644 (file)
@@ -86,6 +86,7 @@ struct scrub_ctx {
        unsigned long long      runtime_errors;
        unsigned long long      errors_found;
        unsigned long long      warnings_found;
+       unsigned long long      inodes_checked;
        bool                    need_repair;
        bool                    preen_triggers[XFS_SCRUB_TYPE_NR];
 };
@@ -95,5 +96,6 @@ 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);
+bool xfs_scan_inodes(struct scrub_ctx *ctx);
 
 #endif /* XFS_SCRUB_XFS_SCRUB_H_ */