]> git.apps.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_scrub: start tracking scrub state in scrub_item
authorDarrick J. Wong <djwong@kernel.org>
Mon, 29 Jul 2024 23:23:07 +0000 (16:23 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:01:07 +0000 (17:01 -0700)
Start using the scrub_item to track which metadata objects need
checking by adding a new flag to the scrub_item state set.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
scrub/phase1.c
scrub/phase2.c
scrub/phase3.c
scrub/phase4.c
scrub/phase5.c
scrub/phase7.c
scrub/scrub.c
scrub/scrub.h

index 1e56f9fb1ee48564fb2e978ccc732c549d79d382..60a8db5724e16a2bda6182f023ea3b745b2a3138 100644 (file)
@@ -61,7 +61,8 @@ report_to_kernel(
                return 0;
 
        scrub_item_init_fs(&sri);
-       ret = scrub_meta_type(ctx, XFS_SCRUB_TYPE_HEALTHY, &sri);
+       scrub_item_schedule(&sri, XFS_SCRUB_TYPE_HEALTHY);
+       ret = scrub_item_check(ctx, &sri);
        if (ret)
                return ret;
 
index 4d90291ed1477616f327d19b5e385497094352f9..79b33dd04dbe2dc4f190758c578e99bd530fa495 100644 (file)
@@ -75,7 +75,8 @@ scan_ag_metadata(
         * First we scrub and fix the AG headers, because we need
         * them to work well enough to check the AG btrees.
         */
-       ret = scrub_ag_headers(ctx, &sri);
+       scrub_item_schedule_group(&sri, XFROG_SCRUB_GROUP_AGHEADER);
+       ret = scrub_item_check(ctx, &sri);
        if (ret)
                goto err;
 
@@ -85,7 +86,8 @@ scan_ag_metadata(
                goto err;
 
        /* Now scrub the AG btrees. */
-       ret = scrub_ag_metadata(ctx, &sri);
+       scrub_item_schedule_group(&sri, XFROG_SCRUB_GROUP_PERAG);
+       ret = scrub_item_check(ctx, &sri);
        if (ret)
                goto err;
 
@@ -131,7 +133,8 @@ scan_fs_metadata(
                goto out;
 
        scrub_item_init_fs(&sri);
-       ret = scrub_meta_type(ctx, type, &sri);
+       scrub_item_schedule(&sri, type);
+       ret = scrub_item_check(ctx, &sri);
        if (ret) {
                sctl->aborted = true;
                goto out;
@@ -189,7 +192,8 @@ phase2_func(
         * If errors occur, this function will log them and return nonzero.
         */
        scrub_item_init_ag(&sri, 0);
-       ret = scrub_meta_type(ctx, XFS_SCRUB_TYPE_SB, &sri);
+       scrub_item_schedule(&sri, XFS_SCRUB_TYPE_SB);
+       ret = scrub_item_check(ctx, &sri);
        if (ret)
                goto out_wq;
        ret = repair_item_completely(ctx, &sri);
index fa2eef4dea190ac0ec2df1c446d13f4d83f8cf38..09347c977b5fe3cc937a83b67a7a09557db2062b 100644 (file)
@@ -144,7 +144,8 @@ scrub_inode(
                fd = scrub_open_handle(handle);
 
        /* Scrub the inode. */
-       error = scrub_file(ctx, fd, bstat, XFS_SCRUB_TYPE_INODE, &sri);
+       scrub_item_schedule(&sri, XFS_SCRUB_TYPE_INODE);
+       error = scrub_item_check_file(ctx, &sri, fd);
        if (error)
                goto out;
 
@@ -153,13 +154,10 @@ scrub_inode(
                goto out;
 
        /* Scrub all block mappings. */
-       error = scrub_file(ctx, fd, bstat, XFS_SCRUB_TYPE_BMBTD, &sri);
-       if (error)
-               goto out;
-       error = scrub_file(ctx, fd, bstat, XFS_SCRUB_TYPE_BMBTA, &sri);
-       if (error)
-               goto out;
-       error = scrub_file(ctx, fd, bstat, XFS_SCRUB_TYPE_BMBTC, &sri);
+       scrub_item_schedule(&sri, XFS_SCRUB_TYPE_BMBTD);
+       scrub_item_schedule(&sri, XFS_SCRUB_TYPE_BMBTA);
+       scrub_item_schedule(&sri, XFS_SCRUB_TYPE_BMBTC);
+       error = scrub_item_check_file(ctx, &sri, fd);
        if (error)
                goto out;
 
@@ -177,27 +175,14 @@ scrub_inode(
         * content scrubbers.  Better to have them return -ENOENT than miss
         * some coverage.
         */
-       if (S_ISLNK(bstat->bs_mode) || !bstat->bs_mode) {
-               /* Check symlink contents. */
-               error = scrub_file(ctx, fd, bstat, XFS_SCRUB_TYPE_SYMLINK,
-                               &sri);
-               if (error)
-                       goto out;
-       }
-       if (S_ISDIR(bstat->bs_mode) || !bstat->bs_mode) {
-               /* Check the directory entries. */
-               error = scrub_file(ctx, fd, bstat, XFS_SCRUB_TYPE_DIR, &sri);
-               if (error)
-                       goto out;
-       }
-
-       /* Check all the extended attributes. */
-       error = scrub_file(ctx, fd, bstat, XFS_SCRUB_TYPE_XATTR, &sri);
-       if (error)
-               goto out;
-
-       /* Check parent pointers. */
-       error = scrub_file(ctx, fd, bstat, XFS_SCRUB_TYPE_PARENT, &sri);
+       if (S_ISLNK(bstat->bs_mode) || !bstat->bs_mode)
+               scrub_item_schedule(&sri, XFS_SCRUB_TYPE_SYMLINK);
+       if (S_ISDIR(bstat->bs_mode) || !bstat->bs_mode)
+               scrub_item_schedule(&sri, XFS_SCRUB_TYPE_DIR);
+
+       scrub_item_schedule(&sri, XFS_SCRUB_TYPE_XATTR);
+       scrub_item_schedule(&sri, XFS_SCRUB_TYPE_PARENT);
+       error = scrub_item_check_file(ctx, &sri, fd);
        if (error)
                goto out;
 
index 230c559f07f3939545bd793bd498100a1baeba49..3c51b38a55e29e4fa7c7c7712ec125dfbc462f4b 100644 (file)
@@ -143,9 +143,7 @@ phase4_func(
         * metadata.  If repairs fails, we'll come back during phase 7.
         */
        scrub_item_init_fs(&sri);
-       ret = scrub_meta_type(ctx, XFS_SCRUB_TYPE_FSCOUNTERS, &sri);
-       if (ret)
-               return ret;
+       scrub_item_schedule(&sri, XFS_SCRUB_TYPE_FSCOUNTERS);
 
        /*
         * Repair possibly bad quota counts before starting other repairs,
@@ -157,13 +155,13 @@ phase4_func(
        if (ret)
                return ret;
 
-       if (fsgeom.sick & XFS_FSOP_GEOM_SICK_QUOTACHECK) {
-               ret = scrub_meta_type(ctx, XFS_SCRUB_TYPE_QUOTACHECK, &sri);
-               if (ret)
-                       return ret;
-       }
+       if (fsgeom.sick & XFS_FSOP_GEOM_SICK_QUOTACHECK)
+               scrub_item_schedule(&sri, XFS_SCRUB_TYPE_QUOTACHECK);
 
-       /* Repair counters before starting on the rest. */
+       /* Check and repair counters before starting on the rest. */
+       ret = scrub_item_check(ctx, &sri);
+       if (ret)
+               return ret;
        ret = repair_item_corruption(ctx, &sri);
        if (ret)
                return ret;
index 6c9a518db4d70286485d58039d9e3c60933f8041..0df8c46e9f5bf0d211f5c4e1fb5abe1e30cb1c8c 100644 (file)
@@ -387,7 +387,6 @@ out:
 struct fs_scan_item {
        struct scrub_item       sri;
        bool                    *abortedp;
-       unsigned int            scrub_type;
 };
 
 /* Run one full-fs scan scrubber in this thread. */
@@ -412,7 +411,7 @@ fs_scan_worker(
                nanosleep(&tv, NULL);
        }
 
-       ret = scrub_meta_type(ctx, item->scrub_type, &item->sri);
+       ret = scrub_item_check(ctx, &item->sri);
        if (ret) {
                str_liberror(ctx, ret, _("checking fs scan metadata"));
                *item->abortedp = true;
@@ -450,7 +449,7 @@ queue_fs_scan(
                return ret;
        }
        scrub_item_init_fs(&item->sri);
-       item->scrub_type = scrub_type;
+       scrub_item_schedule(&item->sri, scrub_type);
        item->abortedp = abortedp;
 
        ret = -workqueue_add(wq, fs_scan_worker, nr, item);
index 02da6b42beb730e5f1890749f39ddfe46bab6102..cd4501f72b725ff71ea58ba9cbbc91be04ef5462 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/fsmap.h>
 #include "libfrog/paths.h"
 #include "libfrog/ptvar.h"
+#include "libfrog/fsgeom.h"
+#include "libfrog/scrub.h"
 #include "list.h"
 #include "xfs_scrub.h"
 #include "common.h"
@@ -118,7 +120,8 @@ phase7_func(
 
        /* Check and fix the summary metadata. */
        scrub_item_init_fs(&sri);
-       error = scrub_summary_metadata(ctx, &sri);
+       scrub_item_schedule_group(&sri, XFROG_SCRUB_GROUP_SUMMARY);
+       error = scrub_item_check(ctx, &sri);
        if (error)
                return error;
        error = repair_item_completely(ctx, &sri);
index 5fc549f97285c1d696d8f3df635fd543eaf96e6f..5aa36a96499d0554da21814f869f7baebca50111 100644 (file)
@@ -86,9 +86,11 @@ xfs_check_metadata(
        bool                            is_inode)
 {
        DEFINE_DESCR(dsc, ctx, format_scrub_descr);
+       enum xfrog_scrub_group          group;
        unsigned int                    tries = 0;
        int                             error;
 
+       group = xfrog_scrubbers[meta->sm_type].group;
        assert(!debug_tweak_on("XFS_SCRUB_NO_KERNEL"));
        assert(meta->sm_type < XFS_SCRUB_TYPE_NR);
        descr_set(&dsc, meta);
@@ -165,7 +167,7 @@ _("Repairs are required."));
         */
        if (is_unoptimized(meta)) {
                if (ctx->mode != SCRUB_MODE_REPAIR) {
-                       if (!is_inode) {
+                       if (group != XFROG_SCRUB_GROUP_INODE) {
                                /* AG or FS metadata, always warn. */
                                str_info(ctx, descr_render(&dsc),
 _("Optimization is possible."));
@@ -223,9 +225,10 @@ _("Optimizations of %s are possible."), _(xfrog_scrubbers[i].descr));
  * Returns 0 for success.  If errors occur, this function will log them and
  * return a positive error code.
  */
-int
+static int
 scrub_meta_type(
        struct scrub_ctx                *ctx,
+       struct xfs_fd                   *xfdp,
        unsigned int                    type,
        struct scrub_item               *sri)
 {
@@ -243,16 +246,20 @@ scrub_meta_type(
                break;
        case XFROG_SCRUB_GROUP_FS:
        case XFROG_SCRUB_GROUP_SUMMARY:
+       case XFROG_SCRUB_GROUP_ISCAN:
        case XFROG_SCRUB_GROUP_NONE:
                break;
-       default:
-               assert(0);
+       case XFROG_SCRUB_GROUP_INODE:
+               meta.sm_ino = sri->sri_ino;
+               meta.sm_gen = sri->sri_gen;
                break;
        }
 
        /* Check the item. */
-       fix = xfs_check_metadata(ctx, &ctx->mnt, &meta, false);
-       progress_add(1);
+       fix = xfs_check_metadata(ctx, xfdp, &meta, false);
+
+       if (xfrog_scrubbers[type].group != XFROG_SCRUB_GROUP_INODE)
+               progress_add(1);
 
        switch (fix) {
        case CHECK_ABORT:
@@ -269,60 +276,54 @@ scrub_meta_type(
        }
 }
 
-/*
- * Scrub all metadata types that are assigned to the given XFROG_SCRUB_GROUP_*,
- * saving corruption reports for later.  This should not be used for
- * XFROG_SCRUB_GROUP_INODE or for checking summary metadata.
- */
-static bool
-scrub_group(
-       struct scrub_ctx                *ctx,
-       enum xfrog_scrub_group          group,
-       struct scrub_item               *sri)
+/* Schedule scrub for all metadata of a given group. */
+void
+scrub_item_schedule_group(
+       struct scrub_item               *sri,
+       enum xfrog_scrub_group          group)
 {
-       const struct xfrog_scrub_descr  *sc;
-       unsigned int                    type;
+       unsigned int                    scrub_type;
 
-       sc = xfrog_scrubbers;
-       for (type = 0; type < XFS_SCRUB_TYPE_NR; type++, sc++) {
-               int                     ret;
-
-               if (sc->group != group)
+       foreach_scrub_type(scrub_type) {
+               if (xfrog_scrubbers[scrub_type].group != group)
                        continue;
-
-               ret = scrub_meta_type(ctx, type, sri);
-               if (ret)
-                       return ret;
+               scrub_item_schedule(sri, scrub_type);
        }
-
-       return 0;
 }
 
-/* Scrub each AG's header blocks. */
+/* Run all the incomplete scans on this scrub principal. */
 int
-scrub_ag_headers(
+scrub_item_check_file(
        struct scrub_ctx                *ctx,
-       struct scrub_item               *sri)
+       struct scrub_item               *sri,
+       int                             override_fd)
 {
-       return scrub_group(ctx, XFROG_SCRUB_GROUP_AGHEADER, sri);
-}
+       struct xfs_fd                   xfd;
+       struct xfs_fd                   *xfdp = &ctx->mnt;
+       unsigned int                    scrub_type;
+       int                             error;
 
-/* Scrub each AG's metadata btrees. */
-int
-scrub_ag_metadata(
-       struct scrub_ctx                *ctx,
-       struct scrub_item               *sri)
-{
-       return scrub_group(ctx, XFROG_SCRUB_GROUP_PERAG, sri);
-}
+       /*
+        * If the caller passed us a file descriptor for a scrub, use it
+        * instead of scrub-by-handle because this enables the kernel to skip
+        * costly inode btree lookups.
+        */
+       if (override_fd >= 0) {
+               memcpy(&xfd, xfdp, sizeof(xfd));
+               xfd.fd = override_fd;
+               xfdp = &xfd;
+       }
 
-/* Scrub all FS summary metadata. */
-int
-scrub_summary_metadata(
-       struct scrub_ctx                *ctx,
-       struct scrub_item               *sri)
-{
-       return scrub_group(ctx, XFROG_SCRUB_GROUP_SUMMARY, sri);
+       foreach_scrub_type(scrub_type) {
+               if (!(sri->sri_state[scrub_type] & SCRUB_ITEM_NEEDSCHECK))
+                       continue;
+
+               error = scrub_meta_type(ctx, xfdp, scrub_type, sri);
+               if (error)
+                       break;
+       }
+
+       return error;
 }
 
 /* How many items do we have to check? */
@@ -374,54 +375,6 @@ scrub_estimate_iscan_work(
        return estimate;
 }
 
-/*
- * Scrub file metadata of some sort.  If errors occur, this function will log
- * them and return nonzero.
- */
-int
-scrub_file(
-       struct scrub_ctx                *ctx,
-       int                             fd,
-       const struct xfs_bulkstat       *bstat,
-       unsigned int                    type,
-       struct scrub_item               *sri)
-{
-       struct xfs_scrub_metadata       meta = {0};
-       struct xfs_fd                   xfd;
-       struct xfs_fd                   *xfdp = &ctx->mnt;
-       enum check_outcome              fix;
-
-       assert(type < XFS_SCRUB_TYPE_NR);
-       assert(xfrog_scrubbers[type].group == XFROG_SCRUB_GROUP_INODE);
-
-       meta.sm_type = type;
-       meta.sm_ino = bstat->bs_ino;
-       meta.sm_gen = bstat->bs_gen;
-
-       /*
-        * If the caller passed us a file descriptor for a scrub, use it
-        * instead of scrub-by-handle because this enables the kernel to skip
-        * costly inode btree lookups.
-        */
-       if (fd >= 0) {
-               memcpy(&xfd, xfdp, sizeof(xfd));
-               xfd.fd = fd;
-               xfdp = &xfd;
-       }
-
-       /* Scrub the piece of metadata. */
-       fix = xfs_check_metadata(ctx, xfdp, &meta, true);
-       if (fix == CHECK_ABORT)
-               return ECANCELED;
-       if (fix == CHECK_DONE) {
-               scrub_item_clean_state(sri, type);
-               return 0;
-       }
-
-       scrub_item_save_state(sri, type, meta.sm_flags);
-       return 0;
-}
-
 /* Dump a scrub item for debugging purposes. */
 void
 scrub_item_dump(
index 3ae0bfd29523577ef038d2cc74e8f92c342f0a73..1ac0d8aed209d52b2cf6f190863653233f55242c 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef XFS_SCRUB_SCRUB_H_
 #define XFS_SCRUB_SCRUB_H_
 
+enum xfrog_scrub_group;
+
 /* Online scrub and repair. */
 enum check_outcome {
        CHECK_DONE,     /* no further processing needed */
@@ -33,6 +35,9 @@ enum check_outcome {
 #define SCRUB_ITEM_XFAIL       (XFS_SCRUB_OFLAG_XFAIL)         /* (1 << 3) */
 #define SCRUB_ITEM_XCORRUPT    (XFS_SCRUB_OFLAG_XCORRUPT)      /* (1 << 4) */
 
+/* This scrub type needs to be checked. */
+#define SCRUB_ITEM_NEEDSCHECK  (1 << 5)
+
 /* All of the state flags that we need to prioritize repair work. */
 #define SCRUB_ITEM_REPAIR_ANY  (SCRUB_ITEM_CORRUPT | \
                                 SCRUB_ITEM_PREEN | \
@@ -96,13 +101,24 @@ scrub_item_init_file(struct scrub_item *sri, const struct xfs_bulkstat *bstat)
 void scrub_item_dump(struct scrub_item *sri, unsigned int group_mask,
                const char *tag);
 
+static inline void
+scrub_item_schedule(struct scrub_item *sri, unsigned int scrub_type)
+{
+       sri->sri_state[scrub_type] = SCRUB_ITEM_NEEDSCHECK;
+}
+
+void scrub_item_schedule_group(struct scrub_item *sri,
+               enum xfrog_scrub_group group);
+int scrub_item_check_file(struct scrub_ctx *ctx, struct scrub_item *sri,
+               int override_fd);
+
+static inline int
+scrub_item_check(struct scrub_ctx *ctx, struct scrub_item *sri)
+{
+       return scrub_item_check_file(ctx, sri, -1);
+}
+
 void scrub_report_preen_triggers(struct scrub_ctx *ctx);
-int scrub_ag_headers(struct scrub_ctx *ctx, struct scrub_item *sri);
-int scrub_ag_metadata(struct scrub_ctx *ctx, struct scrub_item *sri);
-int scrub_iscan_metadata(struct scrub_ctx *ctx, struct scrub_item *sri);
-int scrub_summary_metadata(struct scrub_ctx *ctx, struct scrub_item *sri);
-int scrub_meta_type(struct scrub_ctx *ctx, unsigned int type,
-               struct scrub_item *sri);
 
 bool can_scrub_fs_metadata(struct scrub_ctx *ctx);
 bool can_scrub_inode(struct scrub_ctx *ctx);