diff options
author | Duane Griffin <duaneg@dghda.com> | 2008-07-11 19:27:31 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2008-07-11 19:27:31 -0400 |
commit | 91ef4caf800030fa6e5224b8a41f8c74787b303d (patch) | |
tree | f0c058b50ac2eb9058aa8b077b2da733f8c3ee02 /fs/ext4/ialloc.c | |
parent | bce7f793daec3e65ec5c5705d2457b81fe7b5725 (diff) |
ext4: handle corrupted orphan list at mount
If the orphan node list includes valid, untruncatable nodes with nlink > 0
the ext4_orphan_cleanup loop which attempts to delete them will not do so,
causing it to loop forever. Fix by checking for such nodes in the
ext4_orphan_get function.
This patch fixes the second case (image hdb.20000009.softlockup.gz)
reported in http://bugzilla.kernel.org/show_bug.cgi?id=10882.
Signed-off-by: Duane Griffin <duaneg@dghda.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/ialloc.c')
-rw-r--r-- | fs/ext4/ialloc.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index c6efbab0c801..11cafe14aa27 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -817,6 +817,14 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) | |||
817 | if (IS_ERR(inode)) | 817 | if (IS_ERR(inode)) |
818 | goto iget_failed; | 818 | goto iget_failed; |
819 | 819 | ||
820 | /* | ||
821 | * If the orphans has i_nlinks > 0 then it should be able to be | ||
822 | * truncated, otherwise it won't be removed from the orphan list | ||
823 | * during processing and an infinite loop will result. | ||
824 | */ | ||
825 | if (inode->i_nlink && !ext4_can_truncate(inode)) | ||
826 | goto bad_orphan; | ||
827 | |||
820 | if (NEXT_ORPHAN(inode) > max_ino) | 828 | if (NEXT_ORPHAN(inode) > max_ino) |
821 | goto bad_orphan; | 829 | goto bad_orphan; |
822 | brelse(bitmap_bh); | 830 | brelse(bitmap_bh); |
@@ -838,6 +846,7 @@ bad_orphan: | |||
838 | printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", | 846 | printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n", |
839 | NEXT_ORPHAN(inode)); | 847 | NEXT_ORPHAN(inode)); |
840 | printk(KERN_NOTICE "max_ino=%lu\n", max_ino); | 848 | printk(KERN_NOTICE "max_ino=%lu\n", max_ino); |
849 | printk(KERN_NOTICE "i_nlink=%u\n", inode->i_nlink); | ||
841 | /* Avoid freeing blocks if we got a bad deleted inode */ | 850 | /* Avoid freeing blocks if we got a bad deleted inode */ |
842 | if (inode->i_nlink == 0) | 851 | if (inode->i_nlink == 0) |
843 | inode->i_blocks = 0; | 852 | inode->i_blocks = 0; |