[PATCH 5/5] xfs_scrub: hoist scrub retry loop to scrub_item_check_file

Darrick J. Wong
2023-12-31T22:44:00Z

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 <djwong@kernel.org>
---
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