]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_scrub: detect infinite loops when scanning inodes
authorDarrick J. Wong <djwong@kernel.org>
Fri, 12 Feb 2021 22:23:05 +0000 (17:23 -0500)
committerEric Sandeen <sandeen@sandeen.net>
Fri, 12 Feb 2021 22:23:05 +0000 (17:23 -0500)
During an inode scan (aka phase 3) when we're scanning the inode btree
to find files to check, make sure that each invocation of inumbers
actually gives us an inobt record with a startino that's at least as
large as what we asked for so that we always make forward progress.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
scrub/inodes.c

index 638651139a653de22a47f757d7f12bb98aad0dbe..cc73da7f2008b224aaed4fe8731ccf18170b9db8 100644 (file)
@@ -119,6 +119,7 @@ scan_ag_inodes(
        struct scrub_ctx        *ctx = (struct scrub_ctx *)wq->wq_ctx;
        struct xfs_bulkstat     *bs;
        struct xfs_inumbers     *inumbers;
+       uint64_t                nextino = cvt_agino_to_ino(&ctx->mnt, agno, 0);
        int                     i;
        int                     error;
        int                     stale_count = 0;
@@ -153,6 +154,21 @@ scan_ag_inodes(
        /* Find the inode chunk & alloc mask */
        error = -xfrog_inumbers(&ctx->mnt, ireq);
        while (!error && !si->aborted && ireq->hdr.ocount > 0) {
+               /*
+                * Make sure that we always make forward progress while we
+                * scan the inode btree.
+                */
+               if (nextino > inumbers->xi_startino) {
+                       str_corrupt(ctx, descr,
+       _("AG %u inode btree is corrupt near agino %lu, got %lu"), agno,
+                               cvt_ino_to_agino(&ctx->mnt, nextino),
+                               cvt_ino_to_agino(&ctx->mnt,
+                                               ireq->inumbers[0].xi_startino));
+                       si->aborted = true;
+                       break;
+               }
+               nextino = ireq->hdr.ino;
+
                /*
                 * We can have totally empty inode chunks on filesystems where
                 * there are more than 64 inodes per block.  Skip these.