]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_scrub: selectively re-run bulkstat after re-running inumbers
authorDarrick J. Wong <djwong@kernel.org>
Mon, 24 Feb 2025 18:21:42 +0000 (10:21 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 25 Feb 2025 17:15:56 +0000 (09:15 -0800)
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>
Reviewed-by: Christoph Hellwig <hch@lst.de>
scrub/inodes.c

index c32dfb624e3e95df71af223e1b2b0c4556a9da52..8bdfa0b35d61728a6c420739be8bf90124a29fe2 100644 (file)
@@ -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 @@ retry:
                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."));