forked from Minki/linux
ext4: clean up error handling when orphan list is corrupted
Instead of just printing warning messages, if the orphan list is corrupted, declare the file system is corrupted. If there are any reserved inodes in the orphaned inode list, declare the file system corrupted and stop right away to avoid doing more potential damage to the file system. Cc: stable@vger.kernel.org Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
c9eb13a910
commit
7827a7f6eb
@ -1150,25 +1150,20 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
|
||||
unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count);
|
||||
ext4_group_t block_group;
|
||||
int bit;
|
||||
struct buffer_head *bitmap_bh;
|
||||
struct buffer_head *bitmap_bh = NULL;
|
||||
struct inode *inode = NULL;
|
||||
long err = -EIO;
|
||||
int err = -EFSCORRUPTED;
|
||||
|
||||
/* Error cases - e2fsck has already cleaned up for us */
|
||||
if (ino > max_ino) {
|
||||
ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino);
|
||||
err = -EFSCORRUPTED;
|
||||
goto error;
|
||||
}
|
||||
if (ino < EXT4_FIRST_INO(sb) || ino > max_ino)
|
||||
goto bad_orphan;
|
||||
|
||||
block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
|
||||
bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
|
||||
bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
|
||||
if (IS_ERR(bitmap_bh)) {
|
||||
err = PTR_ERR(bitmap_bh);
|
||||
ext4_warning(sb, "inode bitmap error %ld for orphan %lu",
|
||||
ino, err);
|
||||
goto error;
|
||||
ext4_error(sb, "inode bitmap error %ld for orphan %lu",
|
||||
ino, PTR_ERR(bitmap_bh));
|
||||
return (struct inode *) bitmap_bh;
|
||||
}
|
||||
|
||||
/* Having the inode bit set should be a 100% indicator that this
|
||||
@ -1179,8 +1174,12 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
|
||||
goto bad_orphan;
|
||||
|
||||
inode = ext4_iget(sb, ino);
|
||||
if (IS_ERR(inode))
|
||||
goto iget_failed;
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
|
||||
ino, err);
|
||||
return inode;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the orphans has i_nlinks > 0 then it should be able to
|
||||
@ -1197,29 +1196,25 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
|
||||
brelse(bitmap_bh);
|
||||
return inode;
|
||||
|
||||
iget_failed:
|
||||
err = PTR_ERR(inode);
|
||||
inode = NULL;
|
||||
bad_orphan:
|
||||
ext4_warning(sb, "bad orphan inode %lu! e2fsck was run?", ino);
|
||||
printk(KERN_WARNING "ext4_test_bit(bit=%d, block=%llu) = %d\n",
|
||||
bit, (unsigned long long)bitmap_bh->b_blocknr,
|
||||
ext4_test_bit(bit, bitmap_bh->b_data));
|
||||
printk(KERN_WARNING "inode=%p\n", inode);
|
||||
ext4_error(sb, "bad orphan inode %lu", ino);
|
||||
if (bitmap_bh)
|
||||
printk(KERN_ERR "ext4_test_bit(bit=%d, block=%llu) = %d\n",
|
||||
bit, (unsigned long long)bitmap_bh->b_blocknr,
|
||||
ext4_test_bit(bit, bitmap_bh->b_data));
|
||||
if (inode) {
|
||||
printk(KERN_WARNING "is_bad_inode(inode)=%d\n",
|
||||
printk(KERN_ERR "is_bad_inode(inode)=%d\n",
|
||||
is_bad_inode(inode));
|
||||
printk(KERN_WARNING "NEXT_ORPHAN(inode)=%u\n",
|
||||
printk(KERN_ERR "NEXT_ORPHAN(inode)=%u\n",
|
||||
NEXT_ORPHAN(inode));
|
||||
printk(KERN_WARNING "max_ino=%lu\n", max_ino);
|
||||
printk(KERN_WARNING "i_nlink=%u\n", inode->i_nlink);
|
||||
printk(KERN_ERR "max_ino=%lu\n", max_ino);
|
||||
printk(KERN_ERR "i_nlink=%u\n", inode->i_nlink);
|
||||
/* Avoid freeing blocks if we got a bad deleted inode */
|
||||
if (inode->i_nlink == 0)
|
||||
inode->i_blocks = 0;
|
||||
iput(inode);
|
||||
}
|
||||
brelse(bitmap_bh);
|
||||
error:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user