[PATCH 08/17] xfs_scrub: selectively re-run bulkstat after re-running inumbers

Darrick J. Wong
2025-02-06T22:32:46Z

In the phase 3 inode scan, don't bother retrying the inumbers ->
bulkstat conversion unless inumbers returns the same startino and there
are allocated inodes. If inumbers returns data for a totally different
inobt record, that means the whole inode chunk was freed.

Cc: <linux-xfs@vger.kernel.org> # v5.18.0
Fixes: 245c72a6eeb720 ("xfs_scrub: balance inode chunk scan across CPUs")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
scrub/inodes.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/scrub/inodes.c b/scrub/inodes.c
index c32dfb624e3e95..8bdfa0b35d6172 100644
--- a/scrub/inodes.c
+++ b/scrub/inodes.c
@@ -60,6 +60,8 @@ bulkstat_for_inumbers(
int i;
int error;

+ assert(inumbers->xi_allocmask != 0);
+
/* First we try regular bulkstat, for speed. */
breq->hdr.ino = inumbers->xi_startino;
breq->hdr.icount = inumbers->xi_alloccount;
@@ -246,11 +248,24 @@ scan_ag_bulkstat(
case ESTALE: {
stale_count++;
if (stale_count < 30) {
- ireq->hdr.ino = inumbers->xi_startino;
+ uint64_t old_startino;
+
+ ireq->hdr.ino = old_startino =
+ inumbers->xi_startino;
error = -xfrog_inumbers(&ctx->mnt, ireq);
if (error)
goto err;
- goto retry;
+ /*
+ * Retry only if inumbers returns the same
+ * inobt record as the previous record and
+ * there are allocated inodes in it.
+ */
+ if (!si->aborted &&
+ ireq->hdr.ocount > 0 &&
+ inumbers->xi_alloccount > 0 &&
+ inumbers->xi_startino == old_startino)
+ goto retry;
+ goto out;
}
str_info(ctx, descr_render(&dsc_bulkstat),
_("Changed too many times during scan; giving up."));