Commit e0934da7 authored by Theodore Ts'o's avatar Theodore Ts'o Committed by Sasha Levin

ext4: clean up error handling when orphan list is corrupted

[ Upstream commit 7827a7f6 ]

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: default avatarTheodore Ts'o <tytso@mit.edu>
Signed-off-by: default avatarSasha Levin <sasha.levin@oracle.com>
parent 06c6dcb8
...@@ -1112,22 +1112,20 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) ...@@ -1112,22 +1112,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); unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count);
ext4_group_t block_group; ext4_group_t block_group;
int bit; int bit;
struct buffer_head *bitmap_bh; struct buffer_head *bitmap_bh = NULL;
struct inode *inode = NULL; struct inode *inode = NULL;
long err = -EIO; int err = -EIO;
/* Error cases - e2fsck has already cleaned up for us */ if (ino < EXT4_FIRST_INO(sb) || ino > max_ino)
if (ino > max_ino) { goto bad_orphan;
ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino);
goto error;
}
block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb); block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb); bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
bitmap_bh = ext4_read_inode_bitmap(sb, block_group); bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
if (!bitmap_bh) { if (!bitmap_bh) {
ext4_warning(sb, "inode bitmap error for orphan %lu", ino); ext4_error(sb, "inode bitmap error %ld for orphan %lu",
goto error; ino, PTR_ERR(bitmap_bh));
return (struct inode *) bitmap_bh;
} }
/* Having the inode bit set should be a 100% indicator that this /* Having the inode bit set should be a 100% indicator that this
...@@ -1138,8 +1136,12 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) ...@@ -1138,8 +1136,12 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
goto bad_orphan; goto bad_orphan;
inode = ext4_iget(sb, ino); inode = ext4_iget(sb, ino);
if (IS_ERR(inode)) if (IS_ERR(inode)) {
goto iget_failed; 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 * If the orphans has i_nlinks > 0 then it should be able to
...@@ -1156,29 +1158,25 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) ...@@ -1156,29 +1158,25 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
brelse(bitmap_bh); brelse(bitmap_bh);
return inode; return inode;
iget_failed:
err = PTR_ERR(inode);
inode = NULL;
bad_orphan: bad_orphan:
ext4_warning(sb, "bad orphan inode %lu! e2fsck was run?", ino); ext4_error(sb, "bad orphan inode %lu", ino);
printk(KERN_WARNING "ext4_test_bit(bit=%d, block=%llu) = %d\n", if (bitmap_bh)
bit, (unsigned long long)bitmap_bh->b_blocknr, printk(KERN_ERR "ext4_test_bit(bit=%d, block=%llu) = %d\n",
ext4_test_bit(bit, bitmap_bh->b_data)); bit, (unsigned long long)bitmap_bh->b_blocknr,
printk(KERN_WARNING "inode=%p\n", inode); ext4_test_bit(bit, bitmap_bh->b_data));
if (inode) { if (inode) {
printk(KERN_WARNING "is_bad_inode(inode)=%d\n", printk(KERN_ERR "is_bad_inode(inode)=%d\n",
is_bad_inode(inode)); is_bad_inode(inode));
printk(KERN_WARNING "NEXT_ORPHAN(inode)=%u\n", printk(KERN_ERR "NEXT_ORPHAN(inode)=%u\n",
NEXT_ORPHAN(inode)); NEXT_ORPHAN(inode));
printk(KERN_WARNING "max_ino=%lu\n", max_ino); printk(KERN_ERR "max_ino=%lu\n", max_ino);
printk(KERN_WARNING "i_nlink=%u\n", inode->i_nlink); printk(KERN_ERR "i_nlink=%u\n", inode->i_nlink);
/* Avoid freeing blocks if we got a bad deleted inode */ /* Avoid freeing blocks if we got a bad deleted inode */
if (inode->i_nlink == 0) if (inode->i_nlink == 0)
inode->i_blocks = 0; inode->i_blocks = 0;
iput(inode); iput(inode);
} }
brelse(bitmap_bh); brelse(bitmap_bh);
error:
return ERR_PTR(err); return ERR_PTR(err);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment