diff options
author | Yongqiang Yang <xiaoqiangnk@gmail.com> | 2011-05-03 11:45:29 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-05-03 11:45:29 -0400 |
commit | 197217a5af79c23609da03eda2a52ee8603eec52 (patch) | |
tree | df05721599f21c46fb4879ec3195431dd9a45804 /fs/ext4 | |
parent | df5e6223407e3e645065c4bd968fee007f0e0287 (diff) |
ext4: add a function merging extents right and left
1) Rename ext4_ext_try_to_merge() to ext4_ext_try_to_merge_right().
2) Add a new function ext4_ext_try_to_merge() which tries to merge
an extent both left and right.
3) Use the new function in ext4_ext_convert_unwritten_endio() and
ext4_ext_insert_extent().
Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Tested-by: Allison Henderson <achender@linux.vnet.ibm.com>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/extents.c | 65 |
1 files changed, 36 insertions, 29 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 4890d6f3ad15..23a98b6f00a2 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -1563,7 +1563,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | |||
1563 | * Returns 0 if the extents (ex and ex+1) were _not_ merged and returns | 1563 | * Returns 0 if the extents (ex and ex+1) were _not_ merged and returns |
1564 | * 1 if they got merged. | 1564 | * 1 if they got merged. |
1565 | */ | 1565 | */ |
1566 | static int ext4_ext_try_to_merge(struct inode *inode, | 1566 | static int ext4_ext_try_to_merge_right(struct inode *inode, |
1567 | struct ext4_ext_path *path, | 1567 | struct ext4_ext_path *path, |
1568 | struct ext4_extent *ex) | 1568 | struct ext4_extent *ex) |
1569 | { | 1569 | { |
@@ -1603,6 +1603,31 @@ static int ext4_ext_try_to_merge(struct inode *inode, | |||
1603 | } | 1603 | } |
1604 | 1604 | ||
1605 | /* | 1605 | /* |
1606 | * This function tries to merge the @ex extent to neighbours in the tree. | ||
1607 | * return 1 if merge left else 0. | ||
1608 | */ | ||
1609 | static int ext4_ext_try_to_merge(struct inode *inode, | ||
1610 | struct ext4_ext_path *path, | ||
1611 | struct ext4_extent *ex) { | ||
1612 | struct ext4_extent_header *eh; | ||
1613 | unsigned int depth; | ||
1614 | int merge_done = 0; | ||
1615 | int ret = 0; | ||
1616 | |||
1617 | depth = ext_depth(inode); | ||
1618 | BUG_ON(path[depth].p_hdr == NULL); | ||
1619 | eh = path[depth].p_hdr; | ||
1620 | |||
1621 | if (ex > EXT_FIRST_EXTENT(eh)) | ||
1622 | merge_done = ext4_ext_try_to_merge_right(inode, path, ex - 1); | ||
1623 | |||
1624 | if (!merge_done) | ||
1625 | ret = ext4_ext_try_to_merge_right(inode, path, ex); | ||
1626 | |||
1627 | return ret; | ||
1628 | } | ||
1629 | |||
1630 | /* | ||
1606 | * check if a portion of the "newext" extent overlaps with an | 1631 | * check if a portion of the "newext" extent overlaps with an |
1607 | * existing extent. | 1632 | * existing extent. |
1608 | * | 1633 | * |
@@ -3039,6 +3064,7 @@ fix_extent_len: | |||
3039 | ext4_ext_dirty(handle, inode, path + depth); | 3064 | ext4_ext_dirty(handle, inode, path + depth); |
3040 | return err; | 3065 | return err; |
3041 | } | 3066 | } |
3067 | |||
3042 | static int ext4_convert_unwritten_extents_endio(handle_t *handle, | 3068 | static int ext4_convert_unwritten_extents_endio(handle_t *handle, |
3043 | struct inode *inode, | 3069 | struct inode *inode, |
3044 | struct ext4_ext_path *path) | 3070 | struct ext4_ext_path *path) |
@@ -3047,46 +3073,27 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle, | |||
3047 | struct ext4_extent_header *eh; | 3073 | struct ext4_extent_header *eh; |
3048 | int depth; | 3074 | int depth; |
3049 | int err = 0; | 3075 | int err = 0; |
3050 | int ret = 0; | ||
3051 | 3076 | ||
3052 | depth = ext_depth(inode); | 3077 | depth = ext_depth(inode); |
3053 | eh = path[depth].p_hdr; | 3078 | eh = path[depth].p_hdr; |
3054 | ex = path[depth].p_ext; | 3079 | ex = path[depth].p_ext; |
3055 | 3080 | ||
3081 | ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" | ||
3082 | "block %llu, max_blocks %u\n", inode->i_ino, | ||
3083 | (unsigned long long)le32_to_cpu(ex->ee_block), | ||
3084 | ext4_ext_get_actual_len(ex)); | ||
3085 | |||
3056 | err = ext4_ext_get_access(handle, inode, path + depth); | 3086 | err = ext4_ext_get_access(handle, inode, path + depth); |
3057 | if (err) | 3087 | if (err) |
3058 | goto out; | 3088 | goto out; |
3059 | /* first mark the extent as initialized */ | 3089 | /* first mark the extent as initialized */ |
3060 | ext4_ext_mark_initialized(ex); | 3090 | ext4_ext_mark_initialized(ex); |
3061 | 3091 | ||
3062 | /* | 3092 | /* note: ext4_ext_correct_indexes() isn't needed here because |
3063 | * We have to see if it can be merged with the extent | 3093 | * borders are not changed |
3064 | * on the left. | ||
3065 | */ | 3094 | */ |
3066 | if (ex > EXT_FIRST_EXTENT(eh)) { | 3095 | ext4_ext_try_to_merge(inode, path, ex); |
3067 | /* | 3096 | |
3068 | * To merge left, pass "ex - 1" to try_to_merge(), | ||
3069 | * since it merges towards right _only_. | ||
3070 | */ | ||
3071 | ret = ext4_ext_try_to_merge(inode, path, ex - 1); | ||
3072 | if (ret) { | ||
3073 | err = ext4_ext_correct_indexes(handle, inode, path); | ||
3074 | if (err) | ||
3075 | goto out; | ||
3076 | depth = ext_depth(inode); | ||
3077 | ex--; | ||
3078 | } | ||
3079 | } | ||
3080 | /* | ||
3081 | * Try to Merge towards right. | ||
3082 | */ | ||
3083 | ret = ext4_ext_try_to_merge(inode, path, ex); | ||
3084 | if (ret) { | ||
3085 | err = ext4_ext_correct_indexes(handle, inode, path); | ||
3086 | if (err) | ||
3087 | goto out; | ||
3088 | depth = ext_depth(inode); | ||
3089 | } | ||
3090 | /* Mark modified extent as dirty */ | 3097 | /* Mark modified extent as dirty */ |
3091 | err = ext4_ext_dirty(handle, inode, path + depth); | 3098 | err = ext4_ext_dirty(handle, inode, path + depth); |
3092 | out: | 3099 | out: |