From: Eric Sandeen Date: Thu, 16 Jul 2009 22:00:29 +0000 (-0500) Subject: xfs_repair: clear inodes in incorrect btree format X-Git-Tag: v3.0.3~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e10b140e4a7fa4d4002545645c2014e5e4fa566;p=thirdparty%2Fxfsprogs-dev.git xfs_repair: clear inodes in incorrect btree format 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 Acked-By: Olaf Weber Reviewed-by: Christoph Hellwig --- diff --git a/repair/dinode.c b/repair/dinode.c index 84e1d0598..9da721be4 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -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.