public inbox for linux-ext4@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths
@ 2026-03-23  6:08 Baokun Li
  2026-03-23 10:08 ` Jan Kara
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Baokun Li @ 2026-03-23  6:08 UTC (permalink / raw)
  To: linux-ext4
  Cc: tytso, adilger.kernel, jack, yi.zhang, ojaswin, ritesh.list,
	libaokun, Joseph Qi

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>
---
 fs/ext4/fast_commit.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index f575751f1cae..f1df5581fa96 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -1613,19 +1613,21 @@ static int ext4_fc_replay_inode(struct super_block *sb,
 	/* Immediately update the inode on disk. */
 	ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
 	if (ret)
-		goto out;
+		goto out_brelse;
 	ret = sync_dirty_buffer(iloc.bh);
 	if (ret)
-		goto out;
+		goto out_brelse;
 	ret = ext4_mark_inode_used(sb, ino);
 	if (ret)
-		goto out;
+		goto out_brelse;
 
 	/* Given that we just wrote the inode on disk, this SHOULD succeed. */
 	inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
 	if (IS_ERR(inode)) {
 		ext4_debug("Inode not found.");
-		return -EFSCORRUPTED;
+		inode = NULL;
+		ret = -EFSCORRUPTED;
+		goto out_brelse;
 	}
 
 	/*
@@ -1642,13 +1644,14 @@ static int ext4_fc_replay_inode(struct super_block *sb,
 	ext4_inode_csum_set(inode, ext4_raw_inode(&iloc), EXT4_I(inode));
 	ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
 	sync_dirty_buffer(iloc.bh);
+out_brelse:
 	brelse(iloc.bh);
 out:
 	iput(inode);
 	if (!ret)
 		blkdev_issue_flush(sb->s_bdev);
 
-	return 0;
+	return ret;
 }
 
 /*
-- 
2.43.7


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths
  2026-03-23  6:08 [PATCH] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths Baokun Li
@ 2026-03-23 10:08 ` Jan Kara
  2026-03-23 11:05 ` Zhang Yi
  2026-03-28  5:31 ` Theodore Ts'o
  2 siblings, 0 replies; 4+ messages in thread
From: Jan Kara @ 2026-03-23 10:08 UTC (permalink / raw)
  To: Baokun Li
  Cc: linux-ext4, tytso, adilger.kernel, jack, yi.zhang, ojaswin,
	ritesh.list, Joseph Qi

On Mon 23-03-26 14:08:36, Baokun Li wrote:
> 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>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/ext4/fast_commit.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
> index f575751f1cae..f1df5581fa96 100644
> --- a/fs/ext4/fast_commit.c
> +++ b/fs/ext4/fast_commit.c
> @@ -1613,19 +1613,21 @@ static int ext4_fc_replay_inode(struct super_block *sb,
>  	/* Immediately update the inode on disk. */
>  	ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
>  	if (ret)
> -		goto out;
> +		goto out_brelse;
>  	ret = sync_dirty_buffer(iloc.bh);
>  	if (ret)
> -		goto out;
> +		goto out_brelse;
>  	ret = ext4_mark_inode_used(sb, ino);
>  	if (ret)
> -		goto out;
> +		goto out_brelse;
>  
>  	/* Given that we just wrote the inode on disk, this SHOULD succeed. */
>  	inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
>  	if (IS_ERR(inode)) {
>  		ext4_debug("Inode not found.");
> -		return -EFSCORRUPTED;
> +		inode = NULL;
> +		ret = -EFSCORRUPTED;
> +		goto out_brelse;
>  	}
>  
>  	/*
> @@ -1642,13 +1644,14 @@ static int ext4_fc_replay_inode(struct super_block *sb,
>  	ext4_inode_csum_set(inode, ext4_raw_inode(&iloc), EXT4_I(inode));
>  	ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
>  	sync_dirty_buffer(iloc.bh);
> +out_brelse:
>  	brelse(iloc.bh);
>  out:
>  	iput(inode);
>  	if (!ret)
>  		blkdev_issue_flush(sb->s_bdev);
>  
> -	return 0;
> +	return ret;
>  }
>  
>  /*
> -- 
> 2.43.7
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths
  2026-03-23  6:08 [PATCH] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths Baokun Li
  2026-03-23 10:08 ` Jan Kara
@ 2026-03-23 11:05 ` Zhang Yi
  2026-03-28  5:31 ` Theodore Ts'o
  2 siblings, 0 replies; 4+ messages in thread
From: Zhang Yi @ 2026-03-23 11:05 UTC (permalink / raw)
  To: Baokun Li, linux-ext4
  Cc: tytso, adilger.kernel, jack, ojaswin, ritesh.list, Joseph Qi

On 3/23/2026 2:08 PM, Baokun Li wrote:
> 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>

Looks good to me.

Reviewed-by: Zhang Yi <yi.zhang@huawei.com>

> ---
>  fs/ext4/fast_commit.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
> index f575751f1cae..f1df5581fa96 100644
> --- a/fs/ext4/fast_commit.c
> +++ b/fs/ext4/fast_commit.c
> @@ -1613,19 +1613,21 @@ static int ext4_fc_replay_inode(struct super_block *sb,
>  	/* Immediately update the inode on disk. */
>  	ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
>  	if (ret)
> -		goto out;
> +		goto out_brelse;
>  	ret = sync_dirty_buffer(iloc.bh);
>  	if (ret)
> -		goto out;
> +		goto out_brelse;
>  	ret = ext4_mark_inode_used(sb, ino);
>  	if (ret)
> -		goto out;
> +		goto out_brelse;
>  
>  	/* Given that we just wrote the inode on disk, this SHOULD succeed. */
>  	inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
>  	if (IS_ERR(inode)) {
>  		ext4_debug("Inode not found.");
> -		return -EFSCORRUPTED;
> +		inode = NULL;
> +		ret = -EFSCORRUPTED;
> +		goto out_brelse;
>  	}
>  
>  	/*
> @@ -1642,13 +1644,14 @@ static int ext4_fc_replay_inode(struct super_block *sb,
>  	ext4_inode_csum_set(inode, ext4_raw_inode(&iloc), EXT4_I(inode));
>  	ret = ext4_handle_dirty_metadata(NULL, NULL, iloc.bh);
>  	sync_dirty_buffer(iloc.bh);
> +out_brelse:
>  	brelse(iloc.bh);
>  out:
>  	iput(inode);
>  	if (!ret)
>  		blkdev_issue_flush(sb->s_bdev);
>  
> -	return 0;
> +	return ret;
>  }
>  
>  /*


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths
  2026-03-23  6:08 [PATCH] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths Baokun Li
  2026-03-23 10:08 ` Jan Kara
  2026-03-23 11:05 ` Zhang Yi
@ 2026-03-28  5:31 ` Theodore Ts'o
  2 siblings, 0 replies; 4+ messages in thread
From: Theodore Ts'o @ 2026-03-28  5:31 UTC (permalink / raw)
  To: linux-ext4, Baokun Li
  Cc: Theodore Ts'o, adilger.kernel, jack, yi.zhang, ojaswin,
	ritesh.list, Joseph Qi


On Mon, 23 Mar 2026 14:08:36 +0800, Baokun Li wrote:
> 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:
> 
> [...]

Applied, thanks!

[1/1] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths
      commit: ec0a7500d8eace5b4f305fa0c594dd148f0e8d29

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-03-28  5:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-23  6:08 [PATCH] ext4: fix iloc.bh leak in ext4_fc_replay_inode() error paths Baokun Li
2026-03-23 10:08 ` Jan Kara
2026-03-23 11:05 ` Zhang Yi
2026-03-28  5:31 ` Theodore Ts'o

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox