]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_scrub: ignore freed inodes when single-stepping during phase 3
authorDarrick J. Wong <djwong@kernel.org>
Mon, 24 Feb 2025 18:21:44 +0000 (10:21 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 25 Feb 2025 17:15:57 +0000 (09:15 -0800)
For inodes that inumbers told us were allocated but weren't loaded by
the bulkstat call, we fall back to loading bulkstat data one inode at a
time to try to find the inodes that are too corrupt to load.

However, there are a couple of outcomes of the single bulkstat call that
clearly indicate that the inode is free, not corrupt.  In this case, the
phase 3 inode scan will try to scrub the inode, only to be told ENOENT
because it doesn't exist.

As an optimization here, don't increment ocount, just move on to the
next inode in the mask.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
scrub/inodes.c

index 84696a5bcda7d133dc83e4f722805b717cc35aa9..24a1dcab94c22df71561c6659df8f687e00f08a7 100644 (file)
@@ -160,10 +160,34 @@ bulkstat_single_step(
                 */
                error = -xfrog_bulkstat_single(&ctx->mnt,
                                inumbers->xi_startino + i, breq->hdr.flags, bs);
-               if (error || bs->bs_ino != inumbers->xi_startino + i) {
+               switch (error) {
+               case ENOENT:
+                       /*
+                        * This inode wasn't found, and no results were
+                        * returned.  We've likely hit the end of the
+                        * filesystem, but we'll move on to the next inode in
+                        * the mask for the sake of caution.
+                        */
+                       continue;
+               case 0:
+                       /*
+                        * If a result was returned but it wasn't the inode
+                        * we were looking for, then the missing inode was
+                        * freed.  Move on to the next inode in the mask.
+                        */
+                       if (bs->bs_ino != inumbers->xi_startino + i)
+                               continue;
+                       break;
+               default:
+                       /*
+                        * Some error happened.  Synthesize a bulkstat record
+                        * so that phase3 can try to see if there's a corrupt
+                        * inode that needs repairing.
+                        */
                        memset(bs, 0, sizeof(struct xfs_bulkstat));
                        bs->bs_ino = inumbers->xi_startino + i;
                        bs->bs_blksize = ctx->mnt_sv.f_frsize;
+                       break;
                }
 
                breq->hdr.ocount++;