[PATCH v2] ext4: propagate errors from fast commit range replay

Guanghui Yang posted 1 patch 1 week, 6 days ago
fs/ext4/fast_commit.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
[PATCH v2] ext4: propagate errors from fast commit range replay
Posted by Guanghui Yang 1 week, 6 days ago
ext4_fc_replay() stops replaying fast commit tags only when a tag
handler returns a negative error. However, ext4_fc_replay_add_range()
and ext4_fc_replay_del_range() currently return 0 from their common
exit paths even after internal failures.

This hides errors from ext4_fc_record_modified_inode(),
ext4_map_blocks(), ext4_find_extent(), ext4_ext_insert_extent(),
ext4_ext_replay_update_ex(), and ext4_ext_remove_space(). As a result,
a failed ADD_RANGE or DEL_RANGE replay can be treated as successful and
the replay code may continue with subsequent fast commit tags.

This is particularly problematic for DEL_RANGE because it may already
have marked blocks as free before ext4_ext_remove_space() fails. If the
error is swallowed, replay may continue from a partially applied range
operation.

Return the saved error from the common exit paths and make the
ERR_PTR() cases in ADD_RANGE store PTR_ERR() before jumping to out.

Fixes: 8016e29f4362 ("ext4: fast commit recovery path")
Cc: stable@vger.kernel.org
Fixes: 57a304cfd43b ("btrfs: do not panic in __add_reloc_root")
Signed-off-by: Guanghui Yang <3497809730@qq.com>
---
Changes in v2:
- Add Fixes tag for the commit that made the duplicate-insert error path reachable.

 fs/ext4/fast_commit.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index 8e2259799614..fbb486d917b0 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -2196,8 +2196,11 @@ static int ext4_fc_replay_add_range(struct super_block *sb, u8 *val)
 		if (ret == 0) {
 			/* Range is not mapped */
 			path = ext4_find_extent(inode, cur, path, 0);
-			if (IS_ERR(path))
+			if (IS_ERR(path)) {
+				ret = PTR_ERR(path);
+				path = NULL;
 				goto out;
+			}
 			memset(&newex, 0, sizeof(newex));
 			newex.ee_block = cpu_to_le32(cur);
 			ext4_ext_store_pblock(
@@ -2209,8 +2212,11 @@ static int ext4_fc_replay_add_range(struct super_block *sb, u8 *val)
 			path = ext4_ext_insert_extent(NULL, inode,
 						      path, &newex, 0);
 			up_write((&EXT4_I(inode)->i_data_sem));
-			if (IS_ERR(path))
+			if (IS_ERR(path)) {
+				ret = PTR_ERR(path);
+				path = NULL;
 				goto out;
+			}
 			goto next;
 		}
 
@@ -2257,10 +2263,11 @@ static int ext4_fc_replay_add_range(struct super_block *sb, u8 *val)
 	}
 	ext4_ext_replay_shrink_inode(inode, i_size_read(inode) >>
 					sb->s_blocksize_bits);
+	ret = 0;
 out:
 	ext4_free_ext_path(path);
 	iput(inode);
-	return 0;
+	return ret;
 }
 
 /* Replay DEL_RANGE tag */
@@ -2320,9 +2327,10 @@ ext4_fc_replay_del_range(struct super_block *sb, u8 *val)
 	ext4_ext_replay_shrink_inode(inode,
 		i_size_read(inode) >> sb->s_blocksize_bits);
 	ext4_mark_inode_dirty(NULL, inode);
+	ret = 0;
 out:
 	iput(inode);
-	return 0;
+	return ret;
 }
 
 static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb)
-- 
2.34.1
Re: [PATCH v2] ext4: propagate errors from fast commit range replay
Posted by Qu Wenruo 1 week, 6 days ago

在 2026/7/12 12:41, Guanghui Yang 写道:
> ext4_fc_replay() stops replaying fast commit tags only when a tag
> handler returns a negative error. However, ext4_fc_replay_add_range()
> and ext4_fc_replay_del_range() currently return 0 from their common
> exit paths even after internal failures.
> 
> This hides errors from ext4_fc_record_modified_inode(),
> ext4_map_blocks(), ext4_find_extent(), ext4_ext_insert_extent(),
> ext4_ext_replay_update_ex(), and ext4_ext_remove_space(). As a result,
> a failed ADD_RANGE or DEL_RANGE replay can be treated as successful and
> the replay code may continue with subsequent fast commit tags.
> 
> This is particularly problematic for DEL_RANGE because it may already
> have marked blocks as free before ext4_ext_remove_space() fails. If the
> error is swallowed, replay may continue from a partially applied range
> operation.
> 
> Return the saved error from the common exit paths and make the
> ERR_PTR() cases in ADD_RANGE store PTR_ERR() before jumping to out.
> 
> Fixes: 8016e29f4362 ("ext4: fast commit recovery path")
> Cc: stable@vger.kernel.org
> Fixes: 57a304cfd43b ("btrfs: do not panic in __add_reloc_root")

WTF? Stop hallucinate, no matter if it's from LLM or yourself.

How could a ext4 commit related to btrfs?

> Signed-off-by: Guanghui Yang <3497809730@qq.com>
> ---
> Changes in v2:
> - Add Fixes tag for the commit that made the duplicate-insert error path reachable.
> 
>   fs/ext4/fast_commit.c | 16 ++++++++++++----
>   1 file changed, 12 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
> index 8e2259799614..fbb486d917b0 100644
> --- a/fs/ext4/fast_commit.c
> +++ b/fs/ext4/fast_commit.c
> @@ -2196,8 +2196,11 @@ static int ext4_fc_replay_add_range(struct super_block *sb, u8 *val)
>   		if (ret == 0) {
>   			/* Range is not mapped */
>   			path = ext4_find_extent(inode, cur, path, 0);
> -			if (IS_ERR(path))
> +			if (IS_ERR(path)) {
> +				ret = PTR_ERR(path);
> +				path = NULL;
>   				goto out;
> +			}
>   			memset(&newex, 0, sizeof(newex));
>   			newex.ee_block = cpu_to_le32(cur);
>   			ext4_ext_store_pblock(
> @@ -2209,8 +2212,11 @@ static int ext4_fc_replay_add_range(struct super_block *sb, u8 *val)
>   			path = ext4_ext_insert_extent(NULL, inode,
>   						      path, &newex, 0);
>   			up_write((&EXT4_I(inode)->i_data_sem));
> -			if (IS_ERR(path))
> +			if (IS_ERR(path)) {
> +				ret = PTR_ERR(path);
> +				path = NULL;
>   				goto out;
> +			}
>   			goto next;
>   		}
>   
> @@ -2257,10 +2263,11 @@ static int ext4_fc_replay_add_range(struct super_block *sb, u8 *val)
>   	}
>   	ext4_ext_replay_shrink_inode(inode, i_size_read(inode) >>
>   					sb->s_blocksize_bits);
> +	ret = 0;
>   out:
>   	ext4_free_ext_path(path);
>   	iput(inode);
> -	return 0;
> +	return ret;
>   }
>   
>   /* Replay DEL_RANGE tag */
> @@ -2320,9 +2327,10 @@ ext4_fc_replay_del_range(struct super_block *sb, u8 *val)
>   	ext4_ext_replay_shrink_inode(inode,
>   		i_size_read(inode) >> sb->s_blocksize_bits);
>   	ext4_mark_inode_dirty(NULL, inode);
> +	ret = 0;
>   out:
>   	iput(inode);
> -	return 0;
> +	return ret;
>   }
>   
>   static void ext4_fc_set_bitmaps_and_counters(struct super_block *sb)
Re: [PATCH v2] ext4: propagate errors from fast commit range replay
Posted by Guanghui Yang 1 week, 6 days ago
You are right. This was my mistake.

I accidentally mixed the btrfs v2 Fixes tag into the unrelated ext4
patch while preparing two patches at the same time.

Please disregard the ext4 v2 email entirely. The correct btrfs v2 was
sent separately and is the only patch relevant to the btrfs thread.

Sorry for the confusion.

Guanghui