Commit 567f3e9a authored by Theodore Ts'o's avatar Theodore Ts'o

ext4: plug a buffer_head leak in an error path of ext4_iget()

One of the invalid error paths in ext4_iget() forgot to brelse() the
inode buffer head.  Fix it by adding a brelse() in the common error
return path, which also simplifies function.

Thanks to Andi Kleen <ak@linux.intel.com> reporting the problem.
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 92c28159
...@@ -4781,7 +4781,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4781,7 +4781,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
struct ext4_iloc iloc; struct ext4_iloc iloc;
struct ext4_inode *raw_inode; struct ext4_inode *raw_inode;
struct ext4_inode_info *ei; struct ext4_inode_info *ei;
struct buffer_head *bh;
struct inode *inode; struct inode *inode;
long ret; long ret;
int block; int block;
...@@ -4793,11 +4792,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4793,11 +4792,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
return inode; return inode;
ei = EXT4_I(inode); ei = EXT4_I(inode);
iloc.bh = 0;
ret = __ext4_get_inode_loc(inode, &iloc, 0); ret = __ext4_get_inode_loc(inode, &iloc, 0);
if (ret < 0) if (ret < 0)
goto bad_inode; goto bad_inode;
bh = iloc.bh;
raw_inode = ext4_raw_inode(&iloc); raw_inode = ext4_raw_inode(&iloc);
inode->i_mode = le16_to_cpu(raw_inode->i_mode); inode->i_mode = le16_to_cpu(raw_inode->i_mode);
inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
...@@ -4820,7 +4819,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4820,7 +4819,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
if (inode->i_mode == 0 || if (inode->i_mode == 0 ||
!(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) {
/* this inode is deleted */ /* this inode is deleted */
brelse(bh);
ret = -ESTALE; ret = -ESTALE;
goto bad_inode; goto bad_inode;
} }
...@@ -4852,7 +4850,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4852,7 +4850,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
EXT4_INODE_SIZE(inode->i_sb)) { EXT4_INODE_SIZE(inode->i_sb)) {
brelse(bh);
ret = -EIO; ret = -EIO;
goto bad_inode; goto bad_inode;
} }
...@@ -4905,10 +4902,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4905,10 +4902,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
/* Validate block references which are part of inode */ /* Validate block references which are part of inode */
ret = ext4_check_inode_blockref(inode); ret = ext4_check_inode_blockref(inode);
} }
if (ret) { if (ret)
brelse(bh);
goto bad_inode; goto bad_inode;
}
if (S_ISREG(inode->i_mode)) { if (S_ISREG(inode->i_mode)) {
inode->i_op = &ext4_file_inode_operations; inode->i_op = &ext4_file_inode_operations;
...@@ -4936,7 +4931,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4936,7 +4931,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
init_special_inode(inode, inode->i_mode, init_special_inode(inode, inode->i_mode,
new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
} else { } else {
brelse(bh);
ret = -EIO; ret = -EIO;
ext4_error(inode->i_sb, __func__, ext4_error(inode->i_sb, __func__,
"bogus i_mode (%o) for inode=%lu", "bogus i_mode (%o) for inode=%lu",
...@@ -4949,6 +4943,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) ...@@ -4949,6 +4943,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
return inode; return inode;
bad_inode: bad_inode:
brelse(iloc.bh);
iget_failed(inode); iget_failed(inode);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
......
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