From patchwork Sun Dec 31 22:42:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507938 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5780FC127 for ; Sun, 31 Dec 2023 22:42:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="U/AQtEsE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 261CEC433C7; Sun, 31 Dec 2023 22:42:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062578; bh=bs1KBr9yNiiigik8P1RjQ3ycR8YB3zGKm1vjUb3LIjk=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=U/AQtEsEsMVWTpUttQMq0SJQ1NqOkKGOZJvNuM0vPiegVi2k+mVyDCY46J5zG5ZVN PxebMzZkuvtG+WLSwFoYmUBWjWFqtXJWw4ZbZQUF9FNFHqT7Ca9bbxVy0rEvdMEczn XbImFGfAnBLMmPyDo6OTTlCTMn5d6MJosaGyXOGrNGDzRgpSwzN5XpEJTzwnAGA4n/ 8wL/1BVpaD5vfQCmgkc+V6kZBW1o27LzjRwASaHjYW+7gtUEPl5q2UsqeD4m9wf+kK tROp89lJOAa/0aH3t3qqHG/Zm7dIFuO455vXfJugNYNviwVhEbCDJWxwWnQZrAX8De oA0aPugn3POpA== Date: Sun, 31 Dec 2023 14:42:57 -0800 Subject: [PATCH 1/5] xfs_scrub: start tracking scrub state in scrub_item From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404999877.1798060.11854009505263504940.stgit@frogsfrogsfrogs> In-Reply-To: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> References: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong 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 Reviewed-by: Christoph Hellwig --- scrub/phase1.c | 3 + scrub/phase2.c | 12 +++-- scrub/phase3.c | 41 +++++----------- scrub/phase4.c | 16 +++--- scrub/phase5.c | 5 +- scrub/phase7.c | 5 ++ scrub/scrub.c | 147 +++++++++++++++++++------------------------------------- scrub/scrub.h | 28 ++++++++--- 8 files changed, 108 insertions(+), 149 deletions(-) diff --git a/scrub/phase1.c b/scrub/phase1.c index 1e56f9fb1ee..60a8db5724e 100644 --- a/scrub/phase1.c +++ b/scrub/phase1.c @@ -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; diff --git a/scrub/phase2.c b/scrub/phase2.c index 4d90291ed14..79b33dd04db 100644 --- a/scrub/phase2.c +++ b/scrub/phase2.c @@ -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); diff --git a/scrub/phase3.c b/scrub/phase3.c index fa2eef4dea1..09347c977b5 100644 --- a/scrub/phase3.c +++ b/scrub/phase3.c @@ -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; - } + 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); - /* 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); + 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; diff --git a/scrub/phase4.c b/scrub/phase4.c index 230c559f07f..3c51b38a55e 100644 --- a/scrub/phase4.c +++ b/scrub/phase4.c @@ -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; diff --git a/scrub/phase5.c b/scrub/phase5.c index 6c9a518db4d..0df8c46e9f5 100644 --- a/scrub/phase5.c +++ b/scrub/phase5.c @@ -387,7 +387,6 @@ check_fs_label( 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); diff --git a/scrub/phase7.c b/scrub/phase7.c index 02da6b42beb..cd4501f72b7 100644 --- a/scrub/phase7.c +++ b/scrub/phase7.c @@ -10,6 +10,8 @@ #include #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); diff --git a/scrub/scrub.c b/scrub/scrub.c index 5fc549f9728..5aa36a96499 100644 --- a/scrub/scrub.c +++ b/scrub/scrub.c @@ -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; - - sc = xfrog_scrubbers; - for (type = 0; type < XFS_SCRUB_TYPE_NR; type++, sc++) { - int ret; + unsigned int scrub_type; - 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( diff --git a/scrub/scrub.h b/scrub/scrub.h index 3ae0bfd2952..1ac0d8aed20 100644 --- a/scrub/scrub.h +++ b/scrub/scrub.h @@ -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); From patchwork Sun Dec 31 22:43:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507939 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E574AC127 for ; Sun, 31 Dec 2023 22:43:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NQH9RqSH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AFE69C433C7; Sun, 31 Dec 2023 22:43:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062593; bh=Km+DeKVpOD1HAZJzAnfPgU+8cvFkJzu7UmTeFm/mzVY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=NQH9RqSHyEQ03SbpP4Dx62cjuMDUP7X2WISwEd++twcjyTVmlxplwU5rvoqVjE+5i VKHmCnEj33QOKGFe7aOP2Gd+VnVUm5rQFkdqVSoNjRAD7CLwXZkrYZlqcD2I19bFaO kiA40j+ODGauAD9FtJHtUZNm7LCS/00pEcUecxbL1BijygAjM2inZ3Suz8qBci/Pta z1cDt+wA4mv0NzFNT9Rh0+wDF+zpUfhBhrEFM/zxLWI7t/glH4dfSFv9NNUtMqIbHG uJa+uWU2pY0JZsBL60Uy9iRoZZGmK/fBbUyyBz6QWghIVwZY4G5XEIWCgS4P0DSTAN 5kF2qd4sgevnA== Date: Sun, 31 Dec 2023 14:43:13 -0800 Subject: [PATCH 2/5] xfs_scrub: remove enum check_outcome From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404999891.1798060.18030688801562632472.stgit@frogsfrogsfrogs> In-Reply-To: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> References: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Get rid of this enumeration, and just do what we will directly. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- scrub/repair.c | 56 ++++++++++++++++++++++---------------------------- scrub/scrub.c | 63 +++++++++++++++++++++++++++++--------------------------- scrub/scrub.h | 8 ------- 3 files changed, 58 insertions(+), 69 deletions(-) diff --git a/scrub/repair.c b/scrub/repair.c index a3a8fb311d0..f888441aad0 100644 --- a/scrub/repair.c +++ b/scrub/repair.c @@ -46,7 +46,7 @@ static const unsigned int repair_deps[XFS_SCRUB_TYPE_NR] = { #undef DEP /* Repair some metadata. */ -static enum check_outcome +static int xfs_repair_metadata( struct scrub_ctx *ctx, struct xfs_fd *xfdp, @@ -88,7 +88,7 @@ xfs_repair_metadata( } if (!is_corrupt(&meta) && repair_only) - return CHECK_RETRY; + return 0; memcpy(&oldm, &meta, sizeof(oldm)); oldm.sm_flags = sri->sri_state[scrub_type] & SCRUB_ITEM_REPAIR_ANY; @@ -112,12 +112,12 @@ xfs_repair_metadata( if (debug || verbose) str_info(ctx, descr_render(&dsc), _("Filesystem is busy, deferring repair.")); - return CHECK_RETRY; + return 0; case ESHUTDOWN: /* Filesystem is already shut down, abort. */ str_error(ctx, descr_render(&dsc), _("Filesystem is shut down, aborting.")); - return CHECK_ABORT; + return ECANCELED; case ENOTTY: case EOPNOTSUPP: /* @@ -129,7 +129,7 @@ _("Filesystem is shut down, aborting.")); if (is_unoptimized(&oldm) || debug_tweak_on("XFS_SCRUB_FORCE_REPAIR")) { scrub_item_clean_state(sri, scrub_type); - return CHECK_DONE; + return 0; } /* * If we're in no-complain mode, requeue the check for @@ -140,30 +140,30 @@ _("Filesystem is shut down, aborting.")); * again to see if another repair fixed it. */ if (!(repair_flags & XRM_FINAL_WARNING)) - return CHECK_RETRY; + return 0; fallthrough; case EINVAL: /* Kernel doesn't know how to repair this? */ str_corrupt(ctx, descr_render(&dsc), _("Don't know how to fix; offline repair required.")); scrub_item_clean_state(sri, scrub_type); - return CHECK_DONE; + return 0; case EROFS: /* Read-only filesystem, can't fix. */ if (verbose || debug || needs_repair(&oldm)) str_error(ctx, descr_render(&dsc), _("Read-only filesystem; cannot make changes.")); - return CHECK_ABORT; + return ECANCELED; case ENOENT: /* Metadata not present, just skip it. */ scrub_item_clean_state(sri, scrub_type); - return CHECK_DONE; + return 0; case ENOMEM: case ENOSPC: /* Don't care if preen fails due to low resources. */ if (is_unoptimized(&oldm) && !needs_repair(&oldm)) { scrub_item_clean_state(sri, scrub_type); - return CHECK_DONE; + return 0; } fallthrough; default: @@ -175,10 +175,10 @@ _("Read-only filesystem; cannot make changes.")); * trying to repair it, and bail out. */ if (!(repair_flags & XRM_FINAL_WARNING)) - return CHECK_RETRY; + return 0; str_liberror(ctx, error, descr_render(&dsc)); scrub_item_clean_state(sri, scrub_type); - return CHECK_DONE; + return 0; } /* @@ -201,7 +201,7 @@ _("Read-only filesystem; cannot make changes.")); * log the error loudly and don't try again. */ if (!(repair_flags & XRM_FINAL_WARNING)) - return CHECK_RETRY; + return 0; str_corrupt(ctx, descr_render(&dsc), _("Repair unsuccessful; offline repair required.")); } else if (xref_failed(&meta)) { @@ -219,7 +219,7 @@ _("Repair unsuccessful; offline repair required.")); if (verbose) str_info(ctx, descr_render(&dsc), _("Seems correct but cross-referencing failed; will keep checking.")); - return CHECK_RETRY; + return 0; } } else if (meta.sm_flags & XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED) { if (verbose) @@ -242,7 +242,7 @@ _("Repair unsuccessful; offline repair required.")); } scrub_item_clean_state(sri, scrub_type); - return CHECK_DONE; + return 0; } /* @@ -543,6 +543,7 @@ repair_item_class( struct xfs_fd xfd; struct xfs_fd *xfdp = &ctx->mnt; unsigned int scrub_type; + int error = 0; if (ctx->mode < SCRUB_MODE_REPAIR) return 0; @@ -559,8 +560,6 @@ repair_item_class( } foreach_scrub_type(scrub_type) { - enum check_outcome fix; - if (scrub_excessive_errors(ctx)) return ECANCELED; @@ -576,22 +575,17 @@ repair_item_class( !repair_item_dependencies_ok(sri, scrub_type)) continue; - fix = xfs_repair_metadata(ctx, xfdp, scrub_type, sri, flags); - switch (fix) { - case CHECK_DONE: - if (!(flags & XRM_NOPROGRESS)) - progress_add(1); - continue; - case CHECK_ABORT: - return ECANCELED; - case CHECK_RETRY: - continue; - case CHECK_REPAIR: - abort(); - } + error = xfs_repair_metadata(ctx, xfdp, scrub_type, sri, flags); + if (error) + break; + + /* Maybe update progress if we fixed the problem. */ + if (!(flags & XRM_NOPROGRESS) && + !(sri->sri_state[scrub_type] & SCRUB_ITEM_REPAIR_ANY)) + progress_add(1); } - return 0; + return error; } /* diff --git a/scrub/scrub.c b/scrub/scrub.c index 5aa36a96499..2c47542ee0c 100644 --- a/scrub/scrub.c +++ b/scrub/scrub.c @@ -78,12 +78,12 @@ scrub_warn_incomplete_scrub( } /* Do a read-only check of some metadata. */ -static enum check_outcome +static int xfs_check_metadata( struct scrub_ctx *ctx, struct xfs_fd *xfdp, struct xfs_scrub_metadata *meta, - bool is_inode) + struct scrub_item *sri) { DEFINE_DESCR(dsc, ctx, format_scrub_descr); enum xfrog_scrub_group group; @@ -106,17 +106,18 @@ xfs_check_metadata( break; case ENOENT: /* Metadata not present, just skip it. */ - return CHECK_DONE; + scrub_item_clean_state(sri, meta->sm_type); + return 0; case ESHUTDOWN: /* FS already crashed, give up. */ str_error(ctx, descr_render(&dsc), _("Filesystem is shut down, aborting.")); - return CHECK_ABORT; + return ECANCELED; case EIO: case ENOMEM: /* Abort on I/O errors or insufficient memory. */ str_liberror(ctx, error, descr_render(&dsc)); - return CHECK_ABORT; + return ECANCELED; case EDEADLOCK: case EBUSY: case EFSBADCRC: @@ -124,13 +125,16 @@ _("Filesystem is shut down, aborting.")); /* * The first two should never escape the kernel, * and the other two should be reported via sm_flags. + * Log it and move on. */ str_liberror(ctx, error, _("Kernel bug")); - return CHECK_DONE; + scrub_item_clean_state(sri, meta->sm_type); + return 0; default: - /* Operational error. */ + /* Operational error. Log it and move on. */ str_liberror(ctx, error, descr_render(&dsc)); - return CHECK_DONE; + scrub_item_clean_state(sri, meta->sm_type); + return 0; } /* @@ -153,12 +157,16 @@ _("Filesystem is shut down, aborting.")); */ if (is_corrupt(meta) || xref_disagrees(meta)) { if (ctx->mode < SCRUB_MODE_REPAIR) { + /* Dry-run mode, so log an error and forget it. */ str_corrupt(ctx, descr_render(&dsc), _("Repairs are required.")); - return CHECK_DONE; + scrub_item_clean_state(sri, meta->sm_type); + return 0; } - return CHECK_REPAIR; + /* Schedule repairs. */ + scrub_item_save_state(sri, meta->sm_type, meta->sm_flags); + return 0; } /* @@ -167,6 +175,7 @@ _("Repairs are required.")); */ if (is_unoptimized(meta)) { if (ctx->mode != SCRUB_MODE_REPAIR) { + /* Dry-run mode, so log an error and forget it. */ if (group != XFROG_SCRUB_GROUP_INODE) { /* AG or FS metadata, always warn. */ str_info(ctx, descr_render(&dsc), @@ -178,10 +187,13 @@ _("Optimization is possible.")); ctx->preen_triggers[meta->sm_type] = true; pthread_mutex_unlock(&ctx->lock); } - return CHECK_DONE; + scrub_item_clean_state(sri, meta->sm_type); + return 0; } - return CHECK_REPAIR; + /* Schedule optimizations. */ + scrub_item_save_state(sri, meta->sm_type, meta->sm_flags); + return 0; } /* @@ -191,11 +203,14 @@ _("Optimization is possible.")); * re-examine the object as repairs progress to see if the kernel will * deem it completely consistent at some point. */ - if (xref_failed(meta) && ctx->mode == SCRUB_MODE_REPAIR) - return CHECK_REPAIR; + if (xref_failed(meta) && ctx->mode == SCRUB_MODE_REPAIR) { + scrub_item_save_state(sri, meta->sm_type, meta->sm_flags); + return 0; + } /* Everything is ok. */ - return CHECK_DONE; + scrub_item_clean_state(sri, meta->sm_type); + return 0; } /* Bulk-notify user about things that could be optimized. */ @@ -235,7 +250,7 @@ scrub_meta_type( struct xfs_scrub_metadata meta = { .sm_type = type, }; - enum check_outcome fix; + int error; background_sleep(); @@ -256,24 +271,12 @@ scrub_meta_type( } /* Check the item. */ - fix = xfs_check_metadata(ctx, xfdp, &meta, false); + error = xfs_check_metadata(ctx, xfdp, &meta, sri); if (xfrog_scrubbers[type].group != XFROG_SCRUB_GROUP_INODE) progress_add(1); - switch (fix) { - case CHECK_ABORT: - return ECANCELED; - case CHECK_REPAIR: - scrub_item_save_state(sri, type, meta.sm_flags); - return 0; - case CHECK_DONE: - scrub_item_clean_state(sri, type); - return 0; - default: - /* CHECK_RETRY should never happen. */ - abort(); - } + return error; } /* Schedule scrub for all metadata of a given group. */ diff --git a/scrub/scrub.h b/scrub/scrub.h index 1ac0d8aed20..24fb2444943 100644 --- a/scrub/scrub.h +++ b/scrub/scrub.h @@ -8,14 +8,6 @@ enum xfrog_scrub_group; -/* Online scrub and repair. */ -enum check_outcome { - CHECK_DONE, /* no further processing needed */ - CHECK_REPAIR, /* schedule this for repairs */ - CHECK_ABORT, /* end program */ - CHECK_RETRY, /* repair failed, try again later */ -}; - /* * This flag boosts the repair priority of a scrub item when a dependent scrub * item is scheduled for repair. Use a separate flag to preserve the From patchwork Sun Dec 31 22:43:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507940 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CD6E8C127 for ; Sun, 31 Dec 2023 22:43:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="huMZGAox" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4CEC8C433C7; Sun, 31 Dec 2023 22:43:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062609; bh=XNo+3mE9azj7zisS5vXEwraoFHmI6Nx7bjVty7WYd1E=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=huMZGAoxqwwJMBmbOP4ARAqY20WxTjLRvZTsaa6qvIU96H3KjxvfDtzyTRPC1JGkg hdHWW6Abik3vYPfMLMnbDzCji7XY0QcYF4AFixDa7swrHTIiSzvMmFicpH0qqB/ymW Tp7TcHqmHHJAIt/vX1WFmf83c1rXoOTfojwLGh9TGRhcGPQNYdj4dVsFzW+UGi4qw/ ccPK38AyyEZ6lm+hwBX0RhRM+1X/nuUr4MahPFeGc0pFSrXtgNf7b0XYDRSddfUw+8 /9iWWVMSFprR76w01tlUkGqLrAALs8EEQ8W30YSYaqdhBBL35K1svmdBFNkP/GWcs5 Yx03bAHuEuU+A== Date: Sun, 31 Dec 2023 14:43:28 -0800 Subject: [PATCH 3/5] xfs_scrub: refactor scrub_meta_type out of existence From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404999904.1798060.4622752134580778159.stgit@frogsfrogsfrogs> In-Reply-To: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> References: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Remove this helper function since it's trivial now. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- scrub/scrub.c | 124 ++++++++++++++++++++++++--------------------------------- 1 file changed, 53 insertions(+), 71 deletions(-) diff --git a/scrub/scrub.c b/scrub/scrub.c index 2c47542ee0c..5f0cacbde67 100644 --- a/scrub/scrub.c +++ b/scrub/scrub.c @@ -82,31 +82,51 @@ static int xfs_check_metadata( struct scrub_ctx *ctx, struct xfs_fd *xfdp, - struct xfs_scrub_metadata *meta, + unsigned int scrub_type, struct scrub_item *sri) { DEFINE_DESCR(dsc, ctx, format_scrub_descr); + struct xfs_scrub_metadata meta = { }; enum xfrog_scrub_group group; unsigned int tries = 0; int error; - group = xfrog_scrubbers[meta->sm_type].group; + background_sleep(); + + group = xfrog_scrubbers[scrub_type].group; + meta.sm_type = scrub_type; + switch (group) { + case XFROG_SCRUB_GROUP_AGHEADER: + case XFROG_SCRUB_GROUP_PERAG: + meta.sm_agno = sri->sri_agno; + break; + case XFROG_SCRUB_GROUP_FS: + case XFROG_SCRUB_GROUP_SUMMARY: + case XFROG_SCRUB_GROUP_ISCAN: + case XFROG_SCRUB_GROUP_NONE: + break; + case XFROG_SCRUB_GROUP_INODE: + meta.sm_ino = sri->sri_ino; + meta.sm_gen = sri->sri_gen; + break; + } + assert(!debug_tweak_on("XFS_SCRUB_NO_KERNEL")); - assert(meta->sm_type < XFS_SCRUB_TYPE_NR); - descr_set(&dsc, meta); + assert(scrub_type < XFS_SCRUB_TYPE_NR); + descr_set(&dsc, &meta); - dbg_printf("check %s flags %xh\n", descr_render(&dsc), meta->sm_flags); + dbg_printf("check %s flags %xh\n", descr_render(&dsc), meta.sm_flags); retry: - error = -xfrog_scrub_metadata(xfdp, meta); + error = -xfrog_scrub_metadata(xfdp, &meta); if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR") && !error) - meta->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT; + meta.sm_flags |= XFS_SCRUB_OFLAG_CORRUPT; switch (error) { case 0: /* No operational errors encountered. */ break; case ENOENT: /* Metadata not present, just skip it. */ - scrub_item_clean_state(sri, meta->sm_type); + scrub_item_clean_state(sri, scrub_type); return 0; case ESHUTDOWN: /* FS already crashed, give up. */ @@ -128,12 +148,12 @@ _("Filesystem is shut down, aborting.")); * Log it and move on. */ str_liberror(ctx, error, _("Kernel bug")); - scrub_item_clean_state(sri, meta->sm_type); + scrub_item_clean_state(sri, scrub_type); return 0; default: /* Operational error. Log it and move on. */ str_liberror(ctx, error, descr_render(&dsc)); - scrub_item_clean_state(sri, meta->sm_type); + scrub_item_clean_state(sri, scrub_type); return 0; } @@ -143,29 +163,29 @@ _("Filesystem is shut down, aborting.")); * we'll try the scan again, just in case the fs was busy. * Only retry so many times. */ - if (want_retry(meta) && tries < 10) { + if (want_retry(&meta) && tries < 10) { tries++; goto retry; } /* Complain about incomplete or suspicious metadata. */ - scrub_warn_incomplete_scrub(ctx, &dsc, meta); + scrub_warn_incomplete_scrub(ctx, &dsc, &meta); /* * If we need repairs or there were discrepancies, schedule a * repair if desired, otherwise complain. */ - if (is_corrupt(meta) || xref_disagrees(meta)) { + if (is_corrupt(&meta) || xref_disagrees(&meta)) { if (ctx->mode < SCRUB_MODE_REPAIR) { /* Dry-run mode, so log an error and forget it. */ str_corrupt(ctx, descr_render(&dsc), _("Repairs are required.")); - scrub_item_clean_state(sri, meta->sm_type); + scrub_item_clean_state(sri, scrub_type); return 0; } /* Schedule repairs. */ - scrub_item_save_state(sri, meta->sm_type, meta->sm_flags); + scrub_item_save_state(sri, scrub_type, meta.sm_flags); return 0; } @@ -173,26 +193,26 @@ _("Repairs are required.")); * If we could optimize, schedule a repair if desired, * otherwise complain. */ - if (is_unoptimized(meta)) { + if (is_unoptimized(&meta)) { if (ctx->mode != SCRUB_MODE_REPAIR) { /* Dry-run mode, so log an error and forget it. */ if (group != XFROG_SCRUB_GROUP_INODE) { /* AG or FS metadata, always warn. */ str_info(ctx, descr_render(&dsc), _("Optimization is possible.")); - } else if (!ctx->preen_triggers[meta->sm_type]) { + } else if (!ctx->preen_triggers[scrub_type]) { /* File metadata, only warn once per type. */ pthread_mutex_lock(&ctx->lock); - if (!ctx->preen_triggers[meta->sm_type]) - ctx->preen_triggers[meta->sm_type] = true; + if (!ctx->preen_triggers[scrub_type]) + ctx->preen_triggers[scrub_type] = true; pthread_mutex_unlock(&ctx->lock); } - scrub_item_clean_state(sri, meta->sm_type); + scrub_item_clean_state(sri, scrub_type); return 0; } /* Schedule optimizations. */ - scrub_item_save_state(sri, meta->sm_type, meta->sm_flags); + scrub_item_save_state(sri, scrub_type, meta.sm_flags); return 0; } @@ -203,13 +223,13 @@ _("Optimization is possible.")); * re-examine the object as repairs progress to see if the kernel will * deem it completely consistent at some point. */ - if (xref_failed(meta) && ctx->mode == SCRUB_MODE_REPAIR) { - scrub_item_save_state(sri, meta->sm_type, meta->sm_flags); + if (xref_failed(&meta) && ctx->mode == SCRUB_MODE_REPAIR) { + scrub_item_save_state(sri, scrub_type, meta.sm_flags); return 0; } /* Everything is ok. */ - scrub_item_clean_state(sri, meta->sm_type); + scrub_item_clean_state(sri, scrub_type); return 0; } @@ -233,52 +253,6 @@ _("Optimizations of %s are possible."), _(xfrog_scrubbers[i].descr)); } } -/* - * Scrub a single XFS_SCRUB_TYPE_*, saving corruption reports for later. - * Do not call this function to repair file metadata. - * - * Returns 0 for success. If errors occur, this function will log them and - * return a positive error code. - */ -static int -scrub_meta_type( - struct scrub_ctx *ctx, - struct xfs_fd *xfdp, - unsigned int type, - struct scrub_item *sri) -{ - struct xfs_scrub_metadata meta = { - .sm_type = type, - }; - int error; - - background_sleep(); - - switch (xfrog_scrubbers[type].group) { - case XFROG_SCRUB_GROUP_AGHEADER: - case XFROG_SCRUB_GROUP_PERAG: - meta.sm_agno = sri->sri_agno; - break; - case XFROG_SCRUB_GROUP_FS: - case XFROG_SCRUB_GROUP_SUMMARY: - case XFROG_SCRUB_GROUP_ISCAN: - case XFROG_SCRUB_GROUP_NONE: - break; - case XFROG_SCRUB_GROUP_INODE: - meta.sm_ino = sri->sri_ino; - meta.sm_gen = sri->sri_gen; - break; - } - - /* Check the item. */ - error = xfs_check_metadata(ctx, xfdp, &meta, sri); - - if (xfrog_scrubbers[type].group != XFROG_SCRUB_GROUP_INODE) - progress_add(1); - - return error; -} - /* Schedule scrub for all metadata of a given group. */ void scrub_item_schedule_group( @@ -321,7 +295,15 @@ scrub_item_check_file( if (!(sri->sri_state[scrub_type] & SCRUB_ITEM_NEEDSCHECK)) continue; - error = scrub_meta_type(ctx, xfdp, scrub_type, sri); + error = xfs_check_metadata(ctx, xfdp, scrub_type, sri); + + /* + * Progress is counted by the inode for inode metadata; for + * everything else, it's counted for each scrub call. + */ + if (sri->sri_ino == -1ULL) + progress_add(1); + if (error) break; } From patchwork Sun Dec 31 22:43:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507941 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2A2B8C13B for ; Sun, 31 Dec 2023 22:43:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="avmXFcJW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EE30AC433C7; Sun, 31 Dec 2023 22:43:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062625; bh=ywIHeI2vKlNFjIHJ2ntev86+AjOAWa6m/vv8GLGlHUs=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=avmXFcJWdd60UY86TYTc7HfBCA0NJaIiPKcaQoFSiRK8UyOFppPwTD/rHvBjh7Sj/ B2P0bmZqMU00x6rCvTAmT+Mpyh3BtsaODFL9eunowv6O2Va4PV2fkGyRJCAaWxZ2C3 QjSFZdcI+ewrO1k6wNLyUjQaE2GwScUYzluidvGOCGVN8wLtLW0uosugs7v1RxZ5RJ Dg7bPTf85xbfd2lKhrsC0Gw8rKeGxAiy6jQYHNfRLvArjKA2fBcbD1PlqJpgCckQpd Z3ZntlsoUs1w8S7TetvEreBqpV+LNhgN6bHzIESQM27G9PFhXY8hiAHS4MU2USb7Vt NoIQZqOfjQ/7w== Date: Sun, 31 Dec 2023 14:43:44 -0800 Subject: [PATCH 4/5] xfs_scrub: hoist repair retry loop to repair_item_class From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404999917.1798060.16464082372157795545.stgit@frogsfrogsfrogs> In-Reply-To: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> References: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong For metadata repair calls, move the ioctl retry and freeze permission tracking into scrub_item. This enables us to move the repair retry loop out of xfs_repair_metadata and into its caller to remove a long backwards jump, and gets us closer to vectorizing scrub calls. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- scrub/repair.c | 21 ++++++++++++--------- scrub/scrub.c | 32 ++++++++++++++++++++++++++++++-- scrub/scrub.h | 6 ++++++ scrub/scrub_private.h | 14 ++++++++++++++ 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/scrub/repair.c b/scrub/repair.c index f888441aad0..c427e6e95f0 100644 --- a/scrub/repair.c +++ b/scrub/repair.c @@ -58,7 +58,6 @@ xfs_repair_metadata( struct xfs_scrub_metadata oldm; DEFINE_DESCR(dsc, ctx, format_scrub_descr); bool repair_only; - unsigned int tries = 0; int error; /* @@ -100,7 +99,6 @@ xfs_repair_metadata( str_info(ctx, descr_render(&dsc), _("Attempting optimization.")); -retry: error = -xfrog_scrub_metadata(xfdp, &meta); switch (error) { case 0: @@ -187,10 +185,8 @@ _("Read-only filesystem; cannot make changes.")); * the repair again, just in case the fs was busy. Only retry so many * times. */ - if (want_retry(&meta) && tries < 10) { - tries++; - goto retry; - } + if (want_retry(&meta) && scrub_item_schedule_retry(sri, scrub_type)) + return 0; if (repair_flags & XRM_FINAL_WARNING) scrub_warn_incomplete_scrub(ctx, &dsc, &meta); @@ -541,6 +537,7 @@ repair_item_class( unsigned int flags) { struct xfs_fd xfd; + struct scrub_item old_sri; struct xfs_fd *xfdp = &ctx->mnt; unsigned int scrub_type; int error = 0; @@ -575,9 +572,15 @@ repair_item_class( !repair_item_dependencies_ok(sri, scrub_type)) continue; - error = xfs_repair_metadata(ctx, xfdp, scrub_type, sri, flags); - if (error) - break; + sri->sri_tries[scrub_type] = SCRUB_ITEM_MAX_RETRIES; + do { + memcpy(&old_sri, sri, sizeof(old_sri)); + error = xfs_repair_metadata(ctx, xfdp, scrub_type, sri, + flags); + if (error) + return error; + } while (scrub_item_call_kernel_again(sri, scrub_type, + repair_mask, &old_sri)); /* Maybe update progress if we fixed the problem. */ if (!(flags & XRM_NOPROGRESS) && diff --git a/scrub/scrub.c b/scrub/scrub.c index 5f0cacbde67..8c6bf845fd9 100644 --- a/scrub/scrub.c +++ b/scrub/scrub.c @@ -268,6 +268,34 @@ scrub_item_schedule_group( } } +/* Decide if we call the kernel again to finish scrub/repair activity. */ +bool +scrub_item_call_kernel_again( + struct scrub_item *sri, + unsigned int scrub_type, + uint8_t work_mask, + const struct scrub_item *old) +{ + uint8_t statex; + + /* If there's nothing to do, we're done. */ + if (!(sri->sri_state[scrub_type] & work_mask)) + return false; + + /* + * We are willing to go again if the last call had any effect on the + * state of the scrub item that the caller cares about, if the freeze + * flag got set, or if the kernel asked us to try again... + */ + statex = sri->sri_state[scrub_type] ^ old->sri_state[scrub_type]; + if (statex & work_mask) + return true; + if (sri->sri_tries[scrub_type] != old->sri_tries[scrub_type]) + return true; + + return false; +} + /* Run all the incomplete scans on this scrub principal. */ int scrub_item_check_file( @@ -383,9 +411,9 @@ scrub_item_dump( unsigned int g = 1U << xfrog_scrubbers[i].group; if (g & group_mask) - printf("[%u]: type '%s' state 0x%x\n", i, + printf("[%u]: type '%s' state 0x%x tries %u\n", i, xfrog_scrubbers[i].name, - sri->sri_state[i]); + sri->sri_state[i], sri->sri_tries[i]); } fflush(stdout); } diff --git a/scrub/scrub.h b/scrub/scrub.h index 24fb2444943..246c923f490 100644 --- a/scrub/scrub.h +++ b/scrub/scrub.h @@ -45,6 +45,9 @@ enum xfrog_scrub_group; SCRUB_ITEM_XFAIL | \ SCRUB_ITEM_XCORRUPT) +/* Maximum number of times we'll retry a scrub ioctl call. */ +#define SCRUB_ITEM_MAX_RETRIES 10 + struct scrub_item { /* * Information we need to call the scrub and repair ioctls. Per-AG @@ -58,6 +61,9 @@ struct scrub_item { /* Scrub item state flags, one for each XFS_SCRUB_TYPE. */ __u8 sri_state[XFS_SCRUB_TYPE_NR]; + + /* Track scrub and repair call retries for each scrub type. */ + __u8 sri_tries[XFS_SCRUB_TYPE_NR]; }; #define foreach_scrub_type(loopvar) \ diff --git a/scrub/scrub_private.h b/scrub/scrub_private.h index 53372e1f322..234b30ef2b8 100644 --- a/scrub/scrub_private.h +++ b/scrub/scrub_private.h @@ -89,4 +89,18 @@ scrub_item_type_boosted( return sri->sri_state[scrub_type] & SCRUB_ITEM_BOOST_REPAIR; } +/* Decide if we want to retry this operation and update bookkeeping if yes. */ +static inline bool +scrub_item_schedule_retry(struct scrub_item *sri, unsigned int scrub_type) +{ + if (sri->sri_tries[scrub_type] == 0) + return false; + sri->sri_tries[scrub_type]--; + return true; +} + +bool scrub_item_call_kernel_again(struct scrub_item *sri, + unsigned int scrub_type, uint8_t work_mask, + const struct scrub_item *old); + #endif /* XFS_SCRUB_SCRUB_PRIVATE_H_ */ From patchwork Sun Dec 31 22:44:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13507942 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2A553C140 for ; Sun, 31 Dec 2023 22:44:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FQopkcvn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 979E1C433C8; Sun, 31 Dec 2023 22:44:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1704062640; bh=ZFEhrmrjLxNx/PrG/ryYU2KyercbveM4+sOf1/NInXM=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=FQopkcvnGUwu2uzsgFxbvG1g+7gEpfScmaZwdchtx1sPmbS/DjYEXVkQZF8XT6qw4 V1Wf/bKv3e2MscO/qh6ed1k6qsUNEePipwestOsoc/9NfZ2mHsHDFsskzBMXspmadI HladDifn+SoffOGbiKGhjniduoCg/oST3MywFODbrE//po/aVZgmFasjf44Rp90Rxi N+6UDOO37RJlz/FPfcli+d8rEr0Kw3EkAf4GVHcDEexqbcK2UjCnH8nqm/KeaTNrjI ts6G2ObPznFT7CK7L6UeI60+9o9pu43VymTb2CujQunaaV8MDGtUTOOsyRekfulQhc 7nffa11QpWE3Q== Date: Sun, 31 Dec 2023 14:44:00 -0800 Subject: [PATCH 5/5] xfs_scrub: hoist scrub retry loop to scrub_item_check_file From: "Darrick J. Wong" To: djwong@kernel.org, cem@kernel.org Cc: linux-xfs@vger.kernel.org Message-ID: <170404999930.1798060.1234122907296127847.stgit@frogsfrogsfrogs> In-Reply-To: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> References: <170404999861.1798060.18204009464583067612.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong For metadata check calls, use the ioctl retry and freeze permission tracking in scrub_item that we created in the last patch. This enables us to move the check retry loop out of xfs_scrub_metadata and into its caller to remove a long backwards jump, and gets us closer to vectorizing scrub calls. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- scrub/scrub.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/scrub/scrub.c b/scrub/scrub.c index 8c6bf845fd9..69dfb1eb84d 100644 --- a/scrub/scrub.c +++ b/scrub/scrub.c @@ -88,7 +88,6 @@ xfs_check_metadata( DEFINE_DESCR(dsc, ctx, format_scrub_descr); struct xfs_scrub_metadata meta = { }; enum xfrog_scrub_group group; - unsigned int tries = 0; int error; background_sleep(); @@ -116,7 +115,7 @@ xfs_check_metadata( descr_set(&dsc, &meta); dbg_printf("check %s flags %xh\n", descr_render(&dsc), meta.sm_flags); -retry: + error = -xfrog_scrub_metadata(xfdp, &meta); if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR") && !error) meta.sm_flags |= XFS_SCRUB_OFLAG_CORRUPT; @@ -163,10 +162,8 @@ _("Filesystem is shut down, aborting.")); * we'll try the scan again, just in case the fs was busy. * Only retry so many times. */ - if (want_retry(&meta) && tries < 10) { - tries++; - goto retry; - } + if (want_retry(&meta) && scrub_item_schedule_retry(sri, scrub_type)) + return 0; /* Complain about incomplete or suspicious metadata. */ scrub_warn_incomplete_scrub(ctx, &dsc, &meta); @@ -304,6 +301,7 @@ scrub_item_check_file( int override_fd) { struct xfs_fd xfd; + struct scrub_item old_sri; struct xfs_fd *xfdp = &ctx->mnt; unsigned int scrub_type; int error; @@ -323,7 +321,14 @@ scrub_item_check_file( if (!(sri->sri_state[scrub_type] & SCRUB_ITEM_NEEDSCHECK)) continue; - error = xfs_check_metadata(ctx, xfdp, scrub_type, sri); + sri->sri_tries[scrub_type] = SCRUB_ITEM_MAX_RETRIES; + do { + memcpy(&old_sri, sri, sizeof(old_sri)); + error = xfs_check_metadata(ctx, xfdp, scrub_type, sri); + if (error) + return error; + } while (scrub_item_call_kernel_again(sri, scrub_type, + SCRUB_ITEM_NEEDSCHECK, &old_sri)); /* * Progress is counted by the inode for inode metadata; for