]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_scrub: re-run metafile scrubbers during phase 5
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:24:17 +0000 (16:24 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 28 Nov 2024 02:33:11 +0000 (18:33 -0800)
For metadata files on a metadir filesystem, re-run the scrubbers during
phase 5 to ensure that the metadata files are still connected.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
scrub/phase5.c
scrub/scrub.h

index 69b1cae5c5e2c0957c315c303af13fe42923d084..4d0a76a529b55dc890e3852310fc56802fa2ecd3 100644 (file)
@@ -745,6 +745,87 @@ wait:
        return ret;
 }
 
+/* Queue one metapath scrubber. */
+static int
+queue_metapath_scan(
+       struct workqueue        *wq,
+       bool                    *abortedp,
+       uint64_t                type)
+{
+       struct fs_scan_item     *item;
+       struct scrub_ctx        *ctx = wq->wq_ctx;
+       int                     ret;
+
+       item = malloc(sizeof(struct fs_scan_item));
+       if (!item) {
+               ret = ENOMEM;
+               str_liberror(ctx, ret, _("setting up metapath scan"));
+               return ret;
+       }
+       scrub_item_init_metapath(&item->sri, type);
+       scrub_item_schedule(&item->sri, XFS_SCRUB_TYPE_METAPATH);
+       item->abortedp = abortedp;
+
+       ret = -workqueue_add(wq, fs_scan_worker, 0, item);
+       if (ret)
+               str_liberror(ctx, ret, _("queuing metapath scan work"));
+
+       return ret;
+}
+
+/*
+ * Scrub metadata directory file paths to ensure that fs metadata are still
+ * connected where the fs needs to find them.
+ */
+static int
+run_kernel_metadir_path_scrubbers(
+       struct scrub_ctx        *ctx)
+{
+       struct workqueue        wq;
+       const struct xfrog_scrub_descr  *sc;
+       uint64_t                type;
+       unsigned int            nr_threads = scrub_nproc_workqueue(ctx);
+       bool                    aborted = false;
+       int                     ret, ret2;
+
+       ret = -workqueue_create(&wq, (struct xfs_mount *)ctx, nr_threads);
+       if (ret) {
+               str_liberror(ctx, ret, _("setting up metapath scan workqueue"));
+               return ret;
+       }
+
+       /*
+        * Scan all the metadata files in parallel if metadata directories
+        * are enabled, because the phase 3 scrubbers might have taken out
+        * parts of the metadir tree.
+        */
+       for (type = 0; type < XFS_SCRUB_METAPATH_NR; type++) {
+               sc = &xfrog_metapaths[type];
+               if (sc->group != XFROG_SCRUB_GROUP_FS)
+                       continue;
+
+               ret = queue_metapath_scan(&wq, &aborted, type);
+               if (ret) {
+                       str_liberror(ctx, ret,
+ _("queueing metapath scrub work"));
+                       goto wait;
+               }
+       }
+
+wait:
+       ret2 = -workqueue_terminate(&wq);
+       if (ret2) {
+               str_liberror(ctx, ret2, _("joining metapath scan workqueue"));
+               if (!ret)
+                       ret = ret2;
+       }
+       if (aborted && !ret)
+               ret = ECANCELED;
+
+       workqueue_destroy(&wq);
+       return ret;
+}
+
 /* Check directory connectivity. */
 int
 phase5_func(
@@ -753,6 +834,16 @@ phase5_func(
        struct ncheck_state     ncs = { .ctx = ctx };
        int                     ret;
 
+       /*
+        * Make sure metadata files are still connected to the metadata
+        * directory tree now that phase 3 pruned all corrupt directory tree
+        * links.
+        */
+       if (ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_METADIR) {
+               ret = run_kernel_metadir_path_scrubbers(ctx);
+               if (ret)
+                       return ret;
+       }
 
        /*
         * Check and fix anything that requires a full filesystem scan.  We do
@@ -805,8 +896,12 @@ phase5_estimate(
        unsigned int            *nr_threads,
        int                     *rshift)
 {
+       unsigned int            scans = 2;
+
        *items = scrub_estimate_iscan_work(ctx);
-       *nr_threads = scrub_nproc(ctx) * 2;
+       if (ctx->mnt.fsgeom.flags & XFS_FSOP_GEOM_FLAGS_METADIR)
+               scans++;
+       *nr_threads = scrub_nproc(ctx) * scans;
        *rshift = 0;
        return 0;
 }
index c3eed1b261d51107b1a94da566a8119acac8f394..3bb3ea1d07bf4059b7a21b13caa76a91c464ab4f 100644 (file)
@@ -108,6 +108,13 @@ scrub_item_init_file(struct scrub_item *sri, const struct xfs_bulkstat *bstat)
        sri->sri_gen = bstat->bs_gen;
 }
 
+static inline void
+scrub_item_init_metapath(struct scrub_item *sri, uint64_t metapath)
+{
+       memset(sri, 0, sizeof(*sri));
+       sri->sri_ino = metapath;
+}
+
 void scrub_item_dump(struct scrub_item *sri, unsigned int group_mask,
                const char *tag);