Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 361589
b: refs/heads/master
c: adb2355
h: refs/heads/master
i:
  361587: 5aa1ef6
v: v3
  • Loading branch information
Zheng Liu authored and Theodore Ts'o committed Mar 11, 2013
1 parent d8eedc8 commit bf6e737
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cdee78433c138c2f2018a6884673739af2634787
refs/heads/master: adb2355104b2109e06ba5276485d187d023b2fd2
35 changes: 31 additions & 4 deletions trunk/fs/ext4/extents.c
Original file line number Diff line number Diff line change
Expand Up @@ -2925,7 +2925,7 @@ static int ext4_split_extent_at(handle_t *handle,
{
ext4_fsblk_t newblock;
ext4_lblk_t ee_block;
struct ext4_extent *ex, newex, orig_ex;
struct ext4_extent *ex, newex, orig_ex, zero_ex;
struct ext4_extent *ex2 = NULL;
unsigned int ee_len, depth;
int err = 0;
Expand Down Expand Up @@ -2996,19 +2996,39 @@ static int ext4_split_extent_at(handle_t *handle,
err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
if (split_flag & EXT4_EXT_DATA_VALID1)
if (split_flag & EXT4_EXT_DATA_VALID1) {
err = ext4_ext_zeroout(inode, ex2);
else
zero_ex.ee_block = ex2->ee_block;
zero_ex.ee_len = ext4_ext_get_actual_len(ex2);
ext4_ext_store_pblock(&zero_ex,
ext4_ext_pblock(ex2));
} else {
err = ext4_ext_zeroout(inode, ex);
} else
zero_ex.ee_block = ex->ee_block;
zero_ex.ee_len = ext4_ext_get_actual_len(ex);
ext4_ext_store_pblock(&zero_ex,
ext4_ext_pblock(ex));
}
} else {
err = ext4_ext_zeroout(inode, &orig_ex);
zero_ex.ee_block = orig_ex.ee_block;
zero_ex.ee_len = ext4_ext_get_actual_len(&orig_ex);
ext4_ext_store_pblock(&zero_ex,
ext4_ext_pblock(&orig_ex));
}

if (err)
goto fix_extent_len;
/* update the extent length and mark as initialized */
ex->ee_len = cpu_to_le16(ee_len);
ext4_ext_try_to_merge(handle, inode, path, ex);
err = ext4_ext_dirty(handle, inode, path + path->p_depth);
if (err)
goto fix_extent_len;

/* update extent status tree */
err = ext4_es_zeroout(inode, &zero_ex);

goto out;
} else if (err)
goto fix_extent_len;
Expand Down Expand Up @@ -3150,6 +3170,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
ee_block = le32_to_cpu(ex->ee_block);
ee_len = ext4_ext_get_actual_len(ex);
allocated = ee_len - (map->m_lblk - ee_block);
zero_ex.ee_len = 0;

trace_ext4_ext_convert_to_initialized_enter(inode, map, ex);

Expand Down Expand Up @@ -3247,6 +3268,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
err = ext4_ext_zeroout(inode, ex);
if (err)
goto out;
zero_ex.ee_block = ex->ee_block;
zero_ex.ee_len = ext4_ext_get_actual_len(ex);
ext4_ext_store_pblock(&zero_ex, ext4_ext_pblock(ex));

err = ext4_ext_get_access(handle, inode, path + depth);
if (err)
Expand Down Expand Up @@ -3305,6 +3329,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
err = allocated;

out:
/* If we have gotten a failure, don't zero out status tree */
if (!err)
err = ext4_es_zeroout(inode, &zero_ex);
return err ? err : allocated;
}

Expand Down
17 changes: 17 additions & 0 deletions trunk/fs/ext4/extents_status.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,23 @@ int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
return err;
}

int ext4_es_zeroout(struct inode *inode, struct ext4_extent *ex)
{
ext4_lblk_t ee_block;
ext4_fsblk_t ee_pblock;
unsigned int ee_len;

ee_block = le32_to_cpu(ex->ee_block);
ee_len = ext4_ext_get_actual_len(ex);
ee_pblock = ext4_ext_pblock(ex);

if (ee_len == 0)
return 0;

return ext4_es_insert_extent(inode, ee_block, ee_len, ee_pblock,
EXTENT_STATUS_WRITTEN);
}

static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
{
struct ext4_sb_info *sbi = container_of(shrink,
Expand Down
3 changes: 3 additions & 0 deletions trunk/fs/ext4/extents_status.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
EXTENT_STATUS_DELAYED | \
EXTENT_STATUS_HOLE)

struct ext4_extent;

struct extent_status {
struct rb_node rb_node;
ext4_lblk_t es_lblk; /* first logical block extent covers */
Expand All @@ -64,6 +66,7 @@ extern void ext4_es_find_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
struct extent_status *es);
extern int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
struct extent_status *es);
extern int ext4_es_zeroout(struct inode *inode, struct ext4_extent *ex);

static inline int ext4_es_is_written(struct extent_status *es)
{
Expand Down
10 changes: 10 additions & 0 deletions trunk/fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,15 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
}
#endif

/*
* If the extent has been zeroed out, we don't need to update
* extent status tree.
*/
if ((flags & EXT4_GET_BLOCKS_PRE_IO) &&
ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
if (ext4_es_is_written(&es))
goto has_zeroout;
}
status = map->m_flags & EXT4_MAP_UNWRITTEN ?
EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
Expand All @@ -734,6 +743,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
retval = ret;
}

has_zeroout:
up_write((&EXT4_I(inode)->i_data_sem));
if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
int ret = check_block_validity(inode, map);
Expand Down

0 comments on commit bf6e737

Please sign in to comment.