提交 5f142164 编写于 作者: Z Zhihao Cheng

Revert "ext4: Stop trying writing pages if no free blocks generated"

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I7CBCS
CVE: NA

--------------------------------

This reverts commit 07a8109d.

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: 07a8109d ("ext4: Stop trying writing pages if no free ...")
Signed-off-by: NZhihao Cheng <chengzhihao1@huawei.com>
上级 9e4dad79
...@@ -700,7 +700,6 @@ enum { ...@@ -700,7 +700,6 @@ enum {
#define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010 #define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010
#define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020 #define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020
#define EXT4_FREE_BLOCKS_RERESERVE_CLUSTER 0x0040 #define EXT4_FREE_BLOCKS_RERESERVE_CLUSTER 0x0040
#define EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL 0x0080
/* /*
* ioctl commands * ioctl commands
......
...@@ -1294,8 +1294,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, ...@@ -1294,8 +1294,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
if (!ablocks[i]) if (!ablocks[i])
continue; continue;
ext4_free_blocks(handle, inode, NULL, ablocks[i], 1, ext4_free_blocks(handle, inode, NULL, ablocks[i], 1,
EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_METADATA);
EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL);
} }
} }
kfree(ablocks); kfree(ablocks);
...@@ -4330,7 +4329,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, ...@@ -4330,7 +4329,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
ext4_discard_preallocations(inode, 0); ext4_discard_preallocations(inode, 0);
if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
fb_flags = EXT4_FREE_BLOCKS_NO_QUOT_UPDATE; fb_flags = EXT4_FREE_BLOCKS_NO_QUOT_UPDATE;
fb_flags |= EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL;
ext4_free_blocks(handle, inode, NULL, newblock, ext4_free_blocks(handle, inode, NULL, newblock,
EXT4_C2B(sbi, allocated_clusters), EXT4_C2B(sbi, allocated_clusters),
fb_flags); fb_flags);
......
...@@ -2479,7 +2479,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, ...@@ -2479,7 +2479,7 @@ static int mpage_map_and_submit_extent(handle_t *handle,
* is non-zero, a commit should free up blocks. * is non-zero, a commit should free up blocks.
*/ */
if ((err == -ENOMEM) || if ((err == -ENOMEM) ||
(err == -ENOSPC && EXT4_SB(sb)->s_mb_free_pending)) { (err == -ENOSPC && ext4_count_free_clusters(sb))) {
if (progress) if (progress)
goto update_disksize; goto update_disksize;
return err; return err;
......
...@@ -5498,9 +5498,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, ...@@ -5498,9 +5498,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
* consistency guarantees. * consistency guarantees.
*/ */
if (ext4_handle_valid(handle) && if (ext4_handle_valid(handle) &&
(((flags & EXT4_FREE_BLOCKS_METADATA) || ((flags & EXT4_FREE_BLOCKS_METADATA) ||
!ext4_should_writeback_data(inode)) && !ext4_should_writeback_data(inode))) {
!(flags & EXT4_FREE_BLOCKS_DONT_WAIT_JOURNAL))) {
struct ext4_free_data *new_entry; struct ext4_free_data *new_entry;
/* /*
* We use __GFP_NOFAIL because ext4_free_blocks() is not allowed * We use __GFP_NOFAIL because ext4_free_blocks() is not allowed
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册