|
@@ -3085,7 +3085,6 @@ out:
|
|
|
return err ? err : map->m_len;
|
|
|
}
|
|
|
|
|
|
-#define EXT4_EXT_ZERO_LEN 7
|
|
|
/*
|
|
|
* This function is called by ext4_ext_map_blocks() if someone tries to write
|
|
|
* to an uninitialized extent. It may result in splitting the uninitialized
|
|
@@ -3111,13 +3110,14 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
|
|
|
struct ext4_map_blocks *map,
|
|
|
struct ext4_ext_path *path)
|
|
|
{
|
|
|
+ struct ext4_sb_info *sbi;
|
|
|
struct ext4_extent_header *eh;
|
|
|
struct ext4_map_blocks split_map;
|
|
|
struct ext4_extent zero_ex;
|
|
|
struct ext4_extent *ex;
|
|
|
ext4_lblk_t ee_block, eof_block;
|
|
|
unsigned int ee_len, depth;
|
|
|
- int allocated;
|
|
|
+ int allocated, max_zeroout = 0;
|
|
|
int err = 0;
|
|
|
int split_flag = 0;
|
|
|
|
|
@@ -3125,6 +3125,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
|
|
|
"block %llu, max_blocks %u\n", inode->i_ino,
|
|
|
(unsigned long long)map->m_lblk, map->m_len);
|
|
|
|
|
|
+ sbi = EXT4_SB(inode->i_sb);
|
|
|
eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
|
|
|
inode->i_sb->s_blocksize_bits;
|
|
|
if (eof_block < map->m_lblk + map->m_len)
|
|
@@ -3224,9 +3225,12 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
|
|
|
*/
|
|
|
split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0;
|
|
|
|
|
|
- /* If extent has less than 2*EXT4_EXT_ZERO_LEN zerout directly */
|
|
|
- if (ee_len <= 2*EXT4_EXT_ZERO_LEN &&
|
|
|
- (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
|
|
|
+ if (EXT4_EXT_MAY_ZEROOUT & split_flag)
|
|
|
+ max_zeroout = sbi->s_extent_max_zeroout_kb >>
|
|
|
+ inode->i_sb->s_blocksize_bits;
|
|
|
+
|
|
|
+ /* If extent is less than s_max_zeroout_kb, zeroout directly */
|
|
|
+ if (max_zeroout && (ee_len <= max_zeroout)) {
|
|
|
err = ext4_ext_zeroout(inode, ex);
|
|
|
if (err)
|
|
|
goto out;
|
|
@@ -3250,9 +3254,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
|
|
|
split_map.m_lblk = map->m_lblk;
|
|
|
split_map.m_len = map->m_len;
|
|
|
|
|
|
- if (allocated > map->m_len) {
|
|
|
- if (allocated <= EXT4_EXT_ZERO_LEN &&
|
|
|
- (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
|
|
|
+ if (max_zeroout && (allocated > map->m_len)) {
|
|
|
+ if (allocated <= max_zeroout) {
|
|
|
/* case 3 */
|
|
|
zero_ex.ee_block =
|
|
|
cpu_to_le32(map->m_lblk);
|
|
@@ -3264,9 +3267,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
|
|
|
goto out;
|
|
|
split_map.m_lblk = map->m_lblk;
|
|
|
split_map.m_len = allocated;
|
|
|
- } else if ((map->m_lblk - ee_block + map->m_len <
|
|
|
- EXT4_EXT_ZERO_LEN) &&
|
|
|
- (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
|
|
|
+ } else if (map->m_lblk - ee_block + map->m_len < max_zeroout) {
|
|
|
/* case 2 */
|
|
|
if (map->m_lblk != ee_block) {
|
|
|
zero_ex.ee_block = ex->ee_block;
|
|
@@ -3286,7 +3287,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
|
|
|
}
|
|
|
|
|
|
allocated = ext4_split_extent(handle, inode, path,
|
|
|
- &split_map, split_flag, 0);
|
|
|
+ &split_map, split_flag, 0);
|
|
|
if (allocated < 0)
|
|
|
err = allocated;
|
|
|
|