Revert origin fix, add debug message.
v1->v2: Add commit header in patch 1
Zhihao Cheng (2): Revert "ext4: Stop trying writing pages if no free blocks generated" ext4: Add debug message to notify user space is out of free
fs/ext4/ext4.h | 1 - fs/ext4/extents.c | 4 +--- fs/ext4/inode.c | 16 +++++++++++++++- fs/ext4/mballoc.c | 5 ++--- 4 files changed, 18 insertions(+), 8 deletions(-)
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7CBCS CVE: NA
--------------------------------
This reverts commit 6b84e9d9ab6f6abaae16ca5967300e7f0f15e96a.
When ext4 runs out of space, there could be a potential data lost in ext4_writepages: If there are many preallocated blocks for some files, e4b bitmap is different from block bitmap, and there are more free blocks accounted by block bitmap.
ext4_writepages P2 ext4_mb_new_blocks ext4_map_blocks ext4_mb_regular_allocator // No free bits in e4b bitmap ext4_mb_discard_preallocations_should_retry ext4_mb_discard_preallocations ext4_mb_discard_group_preallocations ext4_mb_release_inode_pa // updates e4b bitmap by pa->pa_free mb_free_blocks ext4_mb_new_blocks ext4_mb_regular_allocator // Got e4b bitmap's free bits ext4_mb_regular_allocator // After 3 times retrying, ret ENOSPC
ext4_writepages mpage_map_and_submit_extent mpage_map_one_extent // ret ENOSPC if (err == -ENOSPC && EXT4_SB(sb)->s_mb_free_pending) // s_mb_free_pending is 0 *give_up_on_write = true // Abandon writeback, data lost!
Fixes: 6b84e9d9ab6f6a ("ext4: Stop trying writing pages if no free ...") Signed-off-by: Zhihao Cheng chengzhihao1@huawei.com --- fs/ext4/ext4.h | 1 - fs/ext4/extents.c | 4 +--- fs/ext4/inode.c | 2 +- fs/ext4/mballoc.c | 5 ++--- 4 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 3165fc239036..6df919b154b4 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -656,7 +656,6 @@ enum { #define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE 0x0008 #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010 #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020 -#define EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL 0x0080
/* * ioctl commands diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 379d91d54d5e..6edab0ef28fd 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1328,8 +1328,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, if (!ablocks[i]) continue; ext4_free_blocks(handle, inode, NULL, ablocks[i], 1, - EXT4_FREE_BLOCKS_METADATA | - EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL); + EXT4_FREE_BLOCKS_METADATA); } } kfree(ablocks); @@ -4607,7 +4606,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, /* not a good idea to call discard here directly, * but otherwise we'd need to call it every free() */ ext4_discard_preallocations(inode); - fb_flags |= EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL; ext4_free_blocks(handle, inode, NULL, newblock, EXT4_C2B(sbi, allocated_clusters), fb_flags); goto out2; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e547abd0cdc4..c40f4442c5c3 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2525,7 +2525,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, * is non-zero, a commit should free up blocks. */ if ((err == -ENOMEM) || - (err == -ENOSPC && EXT4_SB(sb)->s_mb_free_pending)) { + (err == -ENOSPC && ext4_count_free_clusters(sb))) { if (progress) goto update_disksize; return err; diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 84a3e09433ac..a40990da0b62 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4921,9 +4921,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, * consistency guarantees. */ if (ext4_handle_valid(handle) && - (((flags & EXT4_FREE_BLOCKS_METADATA) || - !ext4_should_writeback_data(inode)) && - !(flags & EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL))) { + ((flags & EXT4_FREE_BLOCKS_METADATA) || + !ext4_should_writeback_data(inode))) { struct ext4_free_data *new_entry; /* * We use __GFP_NOFAIL because ext4_free_blocks() is not allowed
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7CBCS CVE: NA
--------------------------------
Add debug message to notify user that ext4_writepages is stuck in loop caused by ENOSPC.
Signed-off-by: Zhihao Cheng chengzhihao1@huawei.com --- fs/ext4/inode.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c40f4442c5c3..d6182e07a530 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2742,6 +2742,9 @@ static int ext4_writepages(struct address_space *mapping, bool done; struct blk_plug plug; bool give_up_on_write = false; + unsigned long retry_warn_ddl = 0; + +#define RETRY_WARN_TIMEOUT (30 * HZ)
if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) return -EIO; @@ -2933,6 +2936,15 @@ static int ext4_writepages(struct address_space *mapping, mpd.io_submit.io_end = NULL;
if (ret == -ENOSPC && sbi->s_journal) { + if (!retry_warn_ddl) { + retry_warn_ddl = jiffies + RETRY_WARN_TIMEOUT; + } else if (time_after(jiffies, retry_warn_ddl)) { + retry_warn_ddl = jiffies + RETRY_WARN_TIMEOUT; + ext4_warning(inode->i_sb, "There are no free blocks available for writing pages, total free %llu, pending free %u, please delete big files to free space", + ext4_count_free_clusters(inode->i_sb), + sbi->s_mb_free_pending); + } + /* * Commit the transaction which would * free blocks released in the transaction @@ -2941,6 +2953,8 @@ static int ext4_writepages(struct address_space *mapping, jbd2_journal_force_commit_nested(sbi->s_journal); ret = 0; continue; + } else { + retry_warn_ddl = 0; } /* Fatal error - ENOMEM, EIO... */ if (ret)
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/1418 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/H...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/1418 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/H...