Skip to content

Commit ec0a750

Browse files
Baokun Litytso
authored andcommitted
ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths
During code review, Joseph found that ext4_fc_replay_inode() calls ext4_get_fc_inode_loc() to get the inode location, which holds a reference to iloc.bh that must be released via brelse(). However, several error paths jump to the 'out' label without releasing iloc.bh: - ext4_handle_dirty_metadata() failure - sync_dirty_buffer() failure - ext4_mark_inode_used() failure - ext4_iget() failure Fix this by introducing an 'out_brelse' label placed just before the existing 'out' label to ensure iloc.bh is always released. Additionally, make ext4_fc_replay_inode() propagate errors properly instead of always returning 0. Reported-by: Joseph Qi <joseph.qi@linux.alibaba.com> Fixes: 8016e29 ("ext4: fast commit recovery path") Signed-off-by: Baokun Li <libaokun@linux.alibaba.com> Reviewed-by: Zhang Yi <yi.zhang@huawei.com> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/20260323060836.3452660-1-libaokun@linux.alibaba.com Signed-off-by: Theodore Ts'o <tytso@mit.edu> Cc: stable@kernel.org
1 parent 0c90eed commit ec0a750

1 file changed

Lines changed: 8 additions & 5 deletions

File tree

fs/ext4/fast_commit.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,19 +1613,21 @@ static int ext4_fc_replay_inode(struct super_block *sb,
16131613
/* Immediately update the inode on disk. */
16141614
ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
16151615
if (ret)
1616-
goto out;
1616+
goto out_brelse;
16171617
ret = sync_dirty_buffer(iloc.bh);
16181618
if (ret)
1619-
goto out;
1619+
goto out_brelse;
16201620
ret = ext4_mark_inode_used(sb, ino);
16211621
if (ret)
1622-
goto out;
1622+
goto out_brelse;
16231623

16241624
/* Given that we just wrote the inode on disk, this SHOULD succeed. */
16251625
inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
16261626
if (IS_ERR(inode)) {
16271627
ext4_debug("Inode not found.");
1628-
return -EFSCORRUPTED;
1628+
inode = NULL;
1629+
ret = -EFSCORRUPTED;
1630+
goto out_brelse;
16291631
}
16301632

16311633
/*
@@ -1642,13 +1644,14 @@ static int ext4_fc_replay_inode(struct super_block *sb,
16421644
ext4_inode_csum_set(inode, ext4_raw_inode(&iloc), EXT4_I(inode));
16431645
ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
16441646
sync_dirty_buffer(iloc.bh);
1647+
out_brelse:
16451648
brelse(iloc.bh);
16461649
out:
16471650
iput(inode);
16481651
if (!ret)
16491652
blkdev_issue_flush(sb->s_bdev);
16501653

1651-
return 0;
1654+
return ret;
16521655
}
16531656

16541657
/*

0 commit comments

Comments
 (0)