]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: clear inodes in incorrect btree format
authorEric Sandeen <sandeen@redhat.com>
Thu, 16 Jul 2009 22:00:29 +0000 (17:00 -0500)
committerEric Sandeen <sandeen@redhat.com>
Thu, 16 Jul 2009 22:00:29 +0000 (17:00 -0500)
See also RH bug #510823:
https://bugzilla.redhat.com/show_bug.cgi?id=510823

This check in xfs_iformat_btree() tripped:

        /*
         * blow out if -- fork has less extents than can fit in
         * fork (fork shouldn't be a btree format), root btree
         * block has more records than can fit into the fork,
         * or the number of extents is greater than the number of
         * blocks.
         */

leading to:

Jul 10 23:22:45 hermes kernel: Filesystem "dm-11": corrupt inode 2339503222
(btree).  Unmount and run xfs_repair.
Jul 10 23:22:45 hermes kernel: Filesystem "dm-11": XFS internal error
xfs_iformat_btree at line 625 of file fs/xfs/xfs_inode.c.

but repair finds nothing at all.  xfs_check, however, does flag the inodes
as problematic:

extent count for ino 2339503222 data fork too low (6) for file format

So I copied the xfs_check test into xfs_repair, and voila, it clears
these inodes.

Ideally repair would move these back into extent format, as long as
they are all valid.  But I need to look further at that, and for now
there is no other way out of the situation when the kernel finds
the problematic inode, so I'll commit this as a first step.

Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
Acked-By: Olaf Weber <olaf@sgi.com>
Reviewed-by: Christoph Hellwig <hch@infradead.org>
repair/dinode.c

index 84e1d05987762d39f4e4e3a851e9cf33c43cd6f1..9da721be464f84a78e3632e577649ae0303d6aa0 100644 (file)
@@ -1280,6 +1280,18 @@ process_btinode(
                        last_key = cursor.level[level-1].first_key;
                }
        }
+       /*
+        * Ideally if all the extents are ok (perhaps after further
+        * checks below?) we'd just move this back into extents format.
+        * But for now clear it, as the kernel will choke on this
+        */
+       if (*nex <= XFS_DFORK_SIZE(dip, mp, whichfork) /
+                       sizeof(xfs_bmbt_rec_t)) {
+               do_warn(
+       _("extent count for ino %lld %s fork too low (%d) for file format\n"),
+                               lino, forkname, *nex);
+               return(1);
+       }
        /*
         * Check that the last child block's forward sibling pointer
         * is NULL.