diff options
author | Theodore Ts'o <tytso@mit.edu> | 2009-11-14 08:19:05 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-11-14 08:19:05 -0500 |
commit | 567f3e9a70d71e5c9be03701b8578be77857293b (patch) | |
tree | 1985907b6d9deffc9d38275c000d7f82d158a93f /fs/ext4 | |
parent | 92c28159dce22913aef6aa811ce6fb0f7f3790b1 (diff) |
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>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/inode.c | 11 |
1 files changed, 3 insertions, 8 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 2c8caa51addb..554c6798597c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4781,7 +4781,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4781 | struct ext4_iloc iloc; | 4781 | struct ext4_iloc iloc; |
4782 | struct ext4_inode *raw_inode; | 4782 | struct ext4_inode *raw_inode; |
4783 | struct ext4_inode_info *ei; | 4783 | struct ext4_inode_info *ei; |
4784 | struct buffer_head *bh; | ||
4785 | struct inode *inode; | 4784 | struct inode *inode; |
4786 | long ret; | 4785 | long ret; |
4787 | int block; | 4786 | int block; |
@@ -4793,11 +4792,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4793 | return inode; | 4792 | return inode; |
4794 | 4793 | ||
4795 | ei = EXT4_I(inode); | 4794 | ei = EXT4_I(inode); |
4795 | iloc.bh = 0; | ||
4796 | 4796 | ||
4797 | ret = __ext4_get_inode_loc(inode, &iloc, 0); | 4797 | ret = __ext4_get_inode_loc(inode, &iloc, 0); |
4798 | if (ret < 0) | 4798 | if (ret < 0) |
4799 | goto bad_inode; | 4799 | goto bad_inode; |
4800 | bh = iloc.bh; | ||
4801 | raw_inode = ext4_raw_inode(&iloc); | 4800 | raw_inode = ext4_raw_inode(&iloc); |
4802 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); | 4801 | inode->i_mode = le16_to_cpu(raw_inode->i_mode); |
4803 | inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low); | 4802 | 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 | if (inode->i_mode == 0 || | 4819 | if (inode->i_mode == 0 || |
4821 | !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { | 4820 | !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { |
4822 | /* this inode is deleted */ | 4821 | /* this inode is deleted */ |
4823 | brelse(bh); | ||
4824 | ret = -ESTALE; | 4822 | ret = -ESTALE; |
4825 | goto bad_inode; | 4823 | goto bad_inode; |
4826 | } | 4824 | } |
@@ -4852,7 +4850,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4852 | ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); | 4850 | ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); |
4853 | if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > | 4851 | if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > |
4854 | EXT4_INODE_SIZE(inode->i_sb)) { | 4852 | EXT4_INODE_SIZE(inode->i_sb)) { |
4855 | brelse(bh); | ||
4856 | ret = -EIO; | 4853 | ret = -EIO; |
4857 | goto bad_inode; | 4854 | goto bad_inode; |
4858 | } | 4855 | } |
@@ -4905,10 +4902,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4905 | /* Validate block references which are part of inode */ | 4902 | /* Validate block references which are part of inode */ |
4906 | ret = ext4_check_inode_blockref(inode); | 4903 | ret = ext4_check_inode_blockref(inode); |
4907 | } | 4904 | } |
4908 | if (ret) { | 4905 | if (ret) |
4909 | brelse(bh); | ||
4910 | goto bad_inode; | 4906 | goto bad_inode; |
4911 | } | ||
4912 | 4907 | ||
4913 | if (S_ISREG(inode->i_mode)) { | 4908 | if (S_ISREG(inode->i_mode)) { |
4914 | inode->i_op = &ext4_file_inode_operations; | 4909 | inode->i_op = &ext4_file_inode_operations; |
@@ -4936,7 +4931,6 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4936 | init_special_inode(inode, inode->i_mode, | 4931 | init_special_inode(inode, inode->i_mode, |
4937 | new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); | 4932 | new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); |
4938 | } else { | 4933 | } else { |
4939 | brelse(bh); | ||
4940 | ret = -EIO; | 4934 | ret = -EIO; |
4941 | ext4_error(inode->i_sb, __func__, | 4935 | ext4_error(inode->i_sb, __func__, |
4942 | "bogus i_mode (%o) for inode=%lu", | 4936 | "bogus i_mode (%o) for inode=%lu", |
@@ -4949,6 +4943,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4949 | return inode; | 4943 | return inode; |
4950 | 4944 | ||
4951 | bad_inode: | 4945 | bad_inode: |
4946 | brelse(iloc.bh); | ||
4952 | iget_failed(inode); | 4947 | iget_failed(inode); |
4953 | return ERR_PTR(ret); | 4948 | return ERR_PTR(ret); |
4954 | } | 4949 | } |