Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 8016e29f4362 ("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

authored by

Baokun Li and committed by
Theodore Ts'o
ec0a7500 0c90eed1

+8 -5
+8 -5
fs/ext4/fast_commit.c
··· 1613 1613 /* Immediately update the inode on disk. */ 1614 1614 ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh); 1615 1615 if (ret) 1616 - goto out; 1616 + goto out_brelse; 1617 1617 ret = sync_dirty_buffer(iloc.bh); 1618 1618 if (ret) 1619 - goto out; 1619 + goto out_brelse; 1620 1620 ret = ext4_mark_inode_used(sb, ino); 1621 1621 if (ret) 1622 - goto out; 1622 + goto out_brelse; 1623 1623 1624 1624 /* Given that we just wrote the inode on disk, this SHOULD succeed. */ 1625 1625 inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL); 1626 1626 if (IS_ERR(inode)) { 1627 1627 ext4_debug("Inode not found."); 1628 - return -EFSCORRUPTED; 1628 + inode = NULL; 1629 + ret = -EFSCORRUPTED; 1630 + goto out_brelse; 1629 1631 } 1630 1632 1631 1633 /* ··· 1644 1642 ext4_inode_csum_set(inode, ext4_raw_inode(&iloc), EXT4_I(inode)); 1645 1643 ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh); 1646 1644 sync_dirty_buffer(iloc.bh); 1645 + out_brelse: 1647 1646 brelse(iloc.bh); 1648 1647 out: 1649 1648 iput(inode); 1650 1649 if (!ret) 1651 1650 blkdev_issue_flush(sb->s_bdev); 1652 1651 1653 - return 0; 1652 + return ret; 1654 1653 } 1655 1654 1656 1655 /*