From: Darrick J. Wong <djwong@xxxxxxxxxx> 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@xxxxxxxxxxxxxxx> # v5.18.0 Fixes: 245c72a6eeb720 ("xfs_scrub: balance inode chunk scan across CPUs") Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- 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."));