summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuanghui Yang <3497809730@qq.com>2026-08-26 06:57:17 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-09-02 14:26:43 +0200
commitffce4ec2e5cc26c8af61046c77602f12e1b34d8b (patch)
treeae1fb04239ad7deda3d0e5de331ac3ae9d59ded3
parentef7048d8a614c5f5a9b20513a5428101a744514e (diff)
downloadlinux-stable-ffce4ec2e5cc26c8af61046c77602f12e1b34d8b.tar.gz
linux-stable-ffce4ec2e5cc26c8af61046c77602f12e1b34d8b.zip
ext4: propagate errors from fast commit range replay
[ Upstream commit d8b8dd3530bf41e14b118702cdaf9de64bb96885 ] 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 Signed-off-by: Guanghui Yang <3497809730@qq.com> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/tencent_E3622146846A84C75C31C7D32AC4D5AD0605@qq.com Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/ext4/fast_commit.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index 26b7782b03f4..4f73f0ad6c85 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -1678,8 +1678,10 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
if (ret == 0) {
/* Range is not mapped */
path = ext4_find_extent(inode, cur, NULL, 0);
- if (IS_ERR(path))
+ if (IS_ERR(path)) {
+ ret = PTR_ERR(path);
goto out;
+ }
memset(&newex, 0, sizeof(newex));
newex.ee_block = cpu_to_le32(cur);
ext4_ext_store_pblock(
@@ -1741,9 +1743,10 @@ next:
}
ext4_ext_replay_shrink_inode(inode, i_size_read(inode) >>
sb->s_blocksize_bits);
+ ret = 0;
out:
iput(inode);
- return 0;
+ return ret;
}
/* Replay DEL_RANGE tag */
@@ -1804,9 +1807,10 @@ ext4_fc_replay_del_range(struct super_block *sb, struct ext4_fc_tl *tl,
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 inline const char *tag2str(u16 tag)