]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_scrub: scan metadata directories during phase 3
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:24:17 +0000 (16:24 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 24 Dec 2024 02:01:26 +0000 (18:01 -0800)
Scan metadata directories for correctness during phase 3.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
scrub/inodes.c
scrub/inodes.h
scrub/phase3.c
scrub/phase5.c
scrub/phase6.c

index 16c79cf495c79359550de1bfc1b6b4a39efcfe2a..3fe759e8f4867d98ff747cadee1ab174221b3ee4 100644 (file)
@@ -56,6 +56,7 @@ bulkstat_for_inumbers(
 {
        struct xfs_bulkstat     *bstat = breq->bulkstat;
        struct xfs_bulkstat     *bs;
+       unsigned int            flags = 0;
        int                     i;
        int                     error;
 
@@ -70,6 +71,9 @@ bulkstat_for_inumbers(
                         strerror_r(error, errbuf, DESCR_BUFSZ));
        }
 
+       if (breq->hdr.flags & XFS_BULK_IREQ_METADIR)
+               flags |= XFS_BULK_IREQ_METADIR;
+
        /*
         * Check each of the stats we got back to make sure we got the inodes
         * we asked for.
@@ -84,7 +88,7 @@ bulkstat_for_inumbers(
 
                /* Load the one inode. */
                error = -xfrog_bulkstat_single(&ctx->mnt,
-                               inumbers->xi_startino + i, 0, bs);
+                               inumbers->xi_startino + i, flags, bs);
                if (error || bs->bs_ino != inumbers->xi_startino + i) {
                        memset(bs, 0, sizeof(struct xfs_bulkstat));
                        bs->bs_ino = inumbers->xi_startino + i;
@@ -100,6 +104,7 @@ struct scan_inodes {
        scrub_inode_iter_fn     fn;
        void                    *arg;
        unsigned int            nr_threads;
+       unsigned int            flags;
        bool                    aborted;
 };
 
@@ -158,6 +163,8 @@ alloc_ichunk(
 
        breq = ichunk_to_bulkstat(ichunk);
        breq->hdr.icount = LIBFROG_BULKSTAT_CHUNKSIZE;
+       if (si->flags & SCRUB_SCAN_METADIR)
+               breq->hdr.flags |= XFS_BULK_IREQ_METADIR;
 
        *ichunkp = ichunk;
        return 0;
@@ -380,10 +387,12 @@ int
 scrub_scan_all_inodes(
        struct scrub_ctx        *ctx,
        scrub_inode_iter_fn     fn,
+       unsigned int            flags,
        void                    *arg)
 {
        struct scan_inodes      si = {
                .fn             = fn,
+               .flags          = flags,
                .arg            = arg,
                .nr_threads     = scrub_nproc_workqueue(ctx),
        };
index 9447fb56aa62e7bb90076b78afe377d07b85d9b8..7a0b275e575eada97399c3c722dec8ccf8933a53 100644 (file)
 typedef int (*scrub_inode_iter_fn)(struct scrub_ctx *ctx,
                struct xfs_handle *handle, struct xfs_bulkstat *bs, void *arg);
 
+/* Return metadata directories too. */
+#define SCRUB_SCAN_METADIR     (1 << 0)
+
 int scrub_scan_all_inodes(struct scrub_ctx *ctx, scrub_inode_iter_fn fn,
-               void *arg);
+               unsigned int flags, void *arg);
 
 int scrub_open_handle(struct xfs_handle *handle);
 
index 046a42c1da8bebcfd82d8994ca33002b2d56579b..c90da78439425a8368fb9a5671d725c1da4322a8 100644 (file)
@@ -312,6 +312,7 @@ phase3_func(
        struct scrub_inode_ctx  ictx = { .ctx = ctx };
        uint64_t                val;
        xfs_agnumber_t          agno;
+       unsigned int            scan_flags = 0;
        int                     err;
 
        err = -ptvar_alloc(scrub_nproc(ctx), sizeof(struct action_list),
@@ -328,6 +329,10 @@ phase3_func(
                goto out_ptvar;
        }
 
+       /* Scan the metadata directory tree too. */
+       if (ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_METADIR)
+               scan_flags |= SCRUB_SCAN_METADIR;
+
        /*
         * If we already have ag/fs metadata to repair from previous phases,
         * we would rather not try to repair file metadata until we've tried
@@ -338,7 +343,7 @@ phase3_func(
                        ictx.always_defer_repairs = true;
        }
 
-       err = scrub_scan_all_inodes(ctx, scrub_inode, &ictx);
+       err = scrub_scan_all_inodes(ctx, scrub_inode, scan_flags, &ictx);
        if (!err && ictx.aborted)
                err = ECANCELED;
        if (err)
index e1d94f9a3568b14724d141199c66d5b1c9e49899..69b1cae5c5e2c0957c315c303af13fe42923d084 100644 (file)
@@ -462,6 +462,9 @@ retry_deferred_inode(
        unsigned int            flags = 0;
        int                     error;
 
+       if (ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_METADIR)
+               flags |= XFS_BULK_IREQ_METADIR;
+
        error = -xfrog_bulkstat_single(&ctx->mnt, ino, flags, &bstat);
        if (error == ENOENT) {
                /* Directory is gone, mark it clear. */
@@ -772,7 +775,7 @@ _("Filesystem has errors, skipping connectivity checks."));
 
        pthread_mutex_init(&ncs.lock, NULL);
 
-       ret = scrub_scan_all_inodes(ctx, check_inode_names, &ncs);
+       ret = scrub_scan_all_inodes(ctx, check_inode_names, 0, &ncs);
        if (ret)
                goto out_lock;
        if (ncs.aborted) {
index 54d21820a722a638e4f3bbc54157f89fd5598ae9..e4f26e7f1dd93e4fba953ab82a20865129c749f4 100644 (file)
@@ -578,7 +578,7 @@ report_all_media_errors(
        }
 
        /* Scan for unlinked files. */
-       return scrub_scan_all_inodes(ctx, report_inode_loss, vs);
+       return scrub_scan_all_inodes(ctx, report_inode_loss, 0, vs);
 }
 
 /* Schedule a read-verify of a (data block) extent. */