Skip to content

Commit 082cd4e

Browse files
Ye Bintytso
authored andcommitted
ext4: fix bug on in ext4_es_cache_extent as ext4_split_extent_at failed
We got follow bug_on when run fsstress with injecting IO fault: [130747.323114] kernel BUG at fs/ext4/extents_status.c:762! [130747.323117] Internal error: Oops - BUG: 0 [Rust-for-Linux#1] SMP ...... [130747.334329] Call trace: [130747.334553] ext4_es_cache_extent+0x150/0x168 [ext4] [130747.334975] ext4_cache_extents+0x64/0xe8 [ext4] [130747.335368] ext4_find_extent+0x300/0x330 [ext4] [130747.335759] ext4_ext_map_blocks+0x74/0x1178 [ext4] [130747.336179] ext4_map_blocks+0x2f4/0x5f0 [ext4] [130747.336567] ext4_mpage_readpages+0x4a8/0x7a8 [ext4] [130747.336995] ext4_readpage+0x54/0x100 [ext4] [130747.337359] generic_file_buffered_read+0x410/0xae8 [130747.337767] generic_file_read_iter+0x114/0x190 [130747.338152] ext4_file_read_iter+0x5c/0x140 [ext4] [130747.338556] __vfs_read+0x11c/0x188 [130747.338851] vfs_read+0x94/0x150 [130747.339110] ksys_read+0x74/0xf0 This patch's modification is according to Jan Kara's suggestion in: https://patchwork.ozlabs.org/project/linux-ext4/patch/20210428085158.3728201-1-yebin10@huawei.com/ "I see. Now I understand your patch. Honestly, seeing how fragile is trying to fix extent tree after split has failed in the middle, I would probably go even further and make sure we fix the tree properly in case of ENOSPC and EDQUOT (those are easily user triggerable). Anything else indicates a HW problem or fs corruption so I'd rather leave the extent tree as is and don't try to fix it (which also means we will not create overlapping extents)." Cc: stable@kernel.org Signed-off-by: Ye Bin <yebin10@huawei.com> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20210506141042.3298679-1-yebin10@huawei.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
1 parent b45f189 commit 082cd4e

File tree

1 file changed

+23
-20
lines changed

1 file changed

+23
-20
lines changed

fs/ext4/extents.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3206,7 +3206,10 @@ static int ext4_split_extent_at(handle_t *handle,
32063206
ext4_ext_mark_unwritten(ex2);
32073207

32083208
err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags);
3209-
if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
3209+
if (err != -ENOSPC && err != -EDQUOT)
3210+
goto out;
3211+
3212+
if (EXT4_EXT_MAY_ZEROOUT & split_flag) {
32103213
if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
32113214
if (split_flag & EXT4_EXT_DATA_VALID1) {
32123215
err = ext4_ext_zeroout(inode, ex2);
@@ -3232,25 +3235,22 @@ static int ext4_split_extent_at(handle_t *handle,
32323235
ext4_ext_pblock(&orig_ex));
32333236
}
32343237

3235-
if (err)
3236-
goto fix_extent_len;
3237-
/* update the extent length and mark as initialized */
3238-
ex->ee_len = cpu_to_le16(ee_len);
3239-
ext4_ext_try_to_merge(handle, inode, path, ex);
3240-
err = ext4_ext_dirty(handle, inode, path + path->p_depth);
3241-
if (err)
3242-
goto fix_extent_len;
3243-
3244-
/* update extent status tree */
3245-
err = ext4_zeroout_es(inode, &zero_ex);
3246-
3247-
goto out;
3248-
} else if (err)
3249-
goto fix_extent_len;
3250-
3251-
out:
3252-
ext4_ext_show_leaf(inode, path);
3253-
return err;
3238+
if (!err) {
3239+
/* update the extent length and mark as initialized */
3240+
ex->ee_len = cpu_to_le16(ee_len);
3241+
ext4_ext_try_to_merge(handle, inode, path, ex);
3242+
err = ext4_ext_dirty(handle, inode, path + path->p_depth);
3243+
if (!err)
3244+
/* update extent status tree */
3245+
err = ext4_zeroout_es(inode, &zero_ex);
3246+
/* If we failed at this point, we don't know in which
3247+
* state the extent tree exactly is so don't try to fix
3248+
* length of the original extent as it may do even more
3249+
* damage.
3250+
*/
3251+
goto out;
3252+
}
3253+
}
32543254

32553255
fix_extent_len:
32563256
ex->ee_len = orig_ex.ee_len;
@@ -3260,6 +3260,9 @@ static int ext4_split_extent_at(handle_t *handle,
32603260
*/
32613261
ext4_ext_dirty(handle, inode, path + path->p_depth);
32623262
return err;
3263+
out:
3264+
ext4_ext_show_leaf(inode, path);
3265+
return err;
32633266
}
32643267

32653268
/*

0 commit comments

Comments
 (0)