aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-11-14 08:19:05 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-11-14 08:19:05 -0500
commit567f3e9a70d71e5c9be03701b8578be77857293b (patch)
tree1985907b6d9deffc9d38275c000d7f82d158a93f /fs/ext4
parent92c28159dce22913aef6aa811ce6fb0f7f3790b1 (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.c11
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
4951bad_inode: 4945bad_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}