mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-14 15:54:15 +08:00
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: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
parent
92c28159dc
commit
567f3e9a70
@ -4781,7 +4781,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
|
||||
struct ext4_iloc iloc;
|
||||
struct ext4_inode *raw_inode;
|
||||
struct ext4_inode_info *ei;
|
||||
struct buffer_head *bh;
|
||||
struct inode *inode;
|
||||
long ret;
|
||||
int block;
|
||||
@ -4793,11 +4792,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
|
||||
return inode;
|
||||
|
||||
ei = EXT4_I(inode);
|
||||
iloc.bh = 0;
|
||||
|
||||
ret = __ext4_get_inode_loc(inode, &iloc, 0);
|
||||
if (ret < 0)
|
||||
goto bad_inode;
|
||||
bh = iloc.bh;
|
||||
raw_inode = ext4_raw_inode(&iloc);
|
||||
inode->i_mode = le16_to_cpu(raw_inode->i_mode);
|
||||
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)
|
||||
if (inode->i_mode == 0 ||
|
||||
!(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) {
|
||||
/* this inode is deleted */
|
||||
brelse(bh);
|
||||
ret = -ESTALE;
|
||||
goto bad_inode;
|
||||
}
|
||||
@ -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);
|
||||
if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
|
||||
EXT4_INODE_SIZE(inode->i_sb)) {
|
||||
brelse(bh);
|
||||
ret = -EIO;
|
||||
goto bad_inode;
|
||||
}
|
||||
@ -4905,10 +4902,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
|
||||
/* Validate block references which are part of inode */
|
||||
ret = ext4_check_inode_blockref(inode);
|
||||
}
|
||||
if (ret) {
|
||||
brelse(bh);
|
||||
if (ret)
|
||||
goto bad_inode;
|
||||
}
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
inode->i_op = &ext4_file_inode_operations;
|
||||
@ -4936,7 +4931,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
|
||||
init_special_inode(inode, inode->i_mode,
|
||||
new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
|
||||
} else {
|
||||
brelse(bh);
|
||||
ret = -EIO;
|
||||
ext4_error(inode->i_sb, __func__,
|
||||
"bogus i_mode (%o) for inode=%lu",
|
||||
@ -4949,6 +4943,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
|
||||
return inode;
|
||||
|
||||
bad_inode:
|
||||
brelse(iloc.bh);
|
||||
iget_failed(inode);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user