aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
authorZheng Liu <wenqing.lz@taobao.com>2013-03-10 21:13:05 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-03-10 21:13:05 -0400
commitadb2355104b2109e06ba5276485d187d023b2fd2 (patch)
treebb5e3ba551ec90d772e9605f21ba99c37119ff37 /fs/ext4/extents.c
parentcdee78433c138c2f2018a6884673739af2634787 (diff)
ext4: update extent status tree after an extent is zeroed out
When we try to split an extent, this extent could be zeroed out and mark as initialized. But we don't know this in ext4_map_blocks because it only returns a length of allocated extent. Meanwhile we will mark this extent as uninitialized because we only check m_flags. This commit update extent status tree when we try to split an unwritten extent. We don't need to worry about the status of this extent because we always mark it as initialized. Signed-off-by: Zheng Liu <wenqing.lz@taobao.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: Dmitry Monakhov <dmonakhov@openvz.org>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 110e85a1f82a..7e37018d1753 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2925,7 +2925,7 @@ static int ext4_split_extent_at(handle_t *handle,
2925{ 2925{
2926 ext4_fsblk_t newblock; 2926 ext4_fsblk_t newblock;
2927 ext4_lblk_t ee_block; 2927 ext4_lblk_t ee_block;
2928 struct ext4_extent *ex, newex, orig_ex; 2928 struct ext4_extent *ex, newex, orig_ex, zero_ex;
2929 struct ext4_extent *ex2 = NULL; 2929 struct ext4_extent *ex2 = NULL;
2930 unsigned int ee_len, depth; 2930 unsigned int ee_len, depth;
2931 int err = 0; 2931 int err = 0;
@@ -2996,12 +2996,26 @@ static int ext4_split_extent_at(handle_t *handle,
2996 err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); 2996 err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
2997 if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { 2997 if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
2998 if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { 2998 if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
2999 if (split_flag & EXT4_EXT_DATA_VALID1) 2999 if (split_flag & EXT4_EXT_DATA_VALID1) {
3000 err = ext4_ext_zeroout(inode, ex2); 3000 err = ext4_ext_zeroout(inode, ex2);
3001 else 3001 zero_ex.ee_block = ex2->ee_block;
3002 zero_ex.ee_len = ext4_ext_get_actual_len(ex2);
3003 ext4_ext_store_pblock(&zero_ex,
3004 ext4_ext_pblock(ex2));
3005 } else {
3002 err = ext4_ext_zeroout(inode, ex); 3006 err = ext4_ext_zeroout(inode, ex);
3003 } else 3007 zero_ex.ee_block = ex->ee_block;
3008 zero_ex.ee_len = ext4_ext_get_actual_len(ex);
3009 ext4_ext_store_pblock(&zero_ex,
3010 ext4_ext_pblock(ex));
3011 }
3012 } else {
3004 err = ext4_ext_zeroout(inode, &orig_ex); 3013 err = ext4_ext_zeroout(inode, &orig_ex);
3014 zero_ex.ee_block = orig_ex.ee_block;
3015 zero_ex.ee_len = ext4_ext_get_actual_len(&orig_ex);
3016 ext4_ext_store_pblock(&zero_ex,
3017 ext4_ext_pblock(&orig_ex));
3018 }
3005 3019
3006 if (err) 3020 if (err)
3007 goto fix_extent_len; 3021 goto fix_extent_len;
@@ -3009,6 +3023,12 @@ static int ext4_split_extent_at(handle_t *handle,
3009 ex->ee_len = cpu_to_le16(ee_len); 3023 ex->ee_len = cpu_to_le16(ee_len);
3010 ext4_ext_try_to_merge(handle, inode, path, ex); 3024 ext4_ext_try_to_merge(handle, inode, path, ex);
3011 err = ext4_ext_dirty(handle, inode, path + path->p_depth); 3025 err = ext4_ext_dirty(handle, inode, path + path->p_depth);
3026 if (err)
3027 goto fix_extent_len;
3028
3029 /* update extent status tree */
3030 err = ext4_es_zeroout(inode, &zero_ex);
3031
3012 goto out; 3032 goto out;
3013 } else if (err) 3033 } else if (err)
3014 goto fix_extent_len; 3034 goto fix_extent_len;
@@ -3150,6 +3170,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
3150 ee_block = le32_to_cpu(ex->ee_block); 3170 ee_block = le32_to_cpu(ex->ee_block);
3151 ee_len = ext4_ext_get_actual_len(ex); 3171 ee_len = ext4_ext_get_actual_len(ex);
3152 allocated = ee_len - (map->m_lblk - ee_block); 3172 allocated = ee_len - (map->m_lblk - ee_block);
3173 zero_ex.ee_len = 0;
3153 3174
3154 trace_ext4_ext_convert_to_initialized_enter(inode, map, ex); 3175 trace_ext4_ext_convert_to_initialized_enter(inode, map, ex);
3155 3176
@@ -3247,6 +3268,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
3247 err = ext4_ext_zeroout(inode, ex); 3268 err = ext4_ext_zeroout(inode, ex);
3248 if (err) 3269 if (err)
3249 goto out; 3270 goto out;
3271 zero_ex.ee_block = ex->ee_block;
3272 zero_ex.ee_len = ext4_ext_get_actual_len(ex);
3273 ext4_ext_store_pblock(&zero_ex, ext4_ext_pblock(ex));
3250 3274
3251 err = ext4_ext_get_access(handle, inode, path + depth); 3275 err = ext4_ext_get_access(handle, inode, path + depth);
3252 if (err) 3276 if (err)
@@ -3305,6 +3329,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
3305 err = allocated; 3329 err = allocated;
3306 3330
3307out: 3331out:
3332 /* If we have gotten a failure, don't zero out status tree */
3333 if (!err)
3334 err = ext4_es_zeroout(inode, &zero_ex);
3308 return err ? err : allocated; 3335 return err ? err : allocated;
3309} 3336}
3310 3337