Commit 197217a5 authored by Yongqiang Yang's avatar Yongqiang Yang Committed by Theodore Ts'o

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: default avatarYongqiang Yang <xiaoqiangnk@gmail.com>
Tested-by: default avatarAllison Henderson <achender@linux.vnet.ibm.com>
parent df5e6223
...@@ -1563,7 +1563,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, ...@@ -1563,7 +1563,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
* Returns 0 if the extents (ex and ex+1) were _not_ merged and returns * Returns 0 if the extents (ex and ex+1) were _not_ merged and returns
* 1 if they got merged. * 1 if they got merged.
*/ */
static int ext4_ext_try_to_merge(struct inode *inode, static int ext4_ext_try_to_merge_right(struct inode *inode,
struct ext4_ext_path *path, struct ext4_ext_path *path,
struct ext4_extent *ex) struct ext4_extent *ex)
{ {
...@@ -1602,6 +1602,31 @@ static int ext4_ext_try_to_merge(struct inode *inode, ...@@ -1602,6 +1602,31 @@ static int ext4_ext_try_to_merge(struct inode *inode,
return merge_done; return merge_done;
} }
/*
* This function tries to merge the @ex extent to neighbours in the tree.
* return 1 if merge left else 0.
*/
static int ext4_ext_try_to_merge(struct inode *inode,
struct ext4_ext_path *path,
struct ext4_extent *ex) {
struct ext4_extent_header *eh;
unsigned int depth;
int merge_done = 0;
int ret = 0;
depth = ext_depth(inode);
BUG_ON(path[depth].p_hdr == NULL);
eh = path[depth].p_hdr;
if (ex > EXT_FIRST_EXTENT(eh))
merge_done = ext4_ext_try_to_merge_right(inode, path, ex - 1);
if (!merge_done)
ret = ext4_ext_try_to_merge_right(inode, path, ex);
return ret;
}
/* /*
* check if a portion of the "newext" extent overlaps with an * check if a portion of the "newext" extent overlaps with an
* existing extent. * existing extent.
...@@ -3039,6 +3064,7 @@ static int ext4_split_unwritten_extents(handle_t *handle, ...@@ -3039,6 +3064,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
ext4_ext_dirty(handle, inode, path + depth); ext4_ext_dirty(handle, inode, path + depth);
return err; return err;
} }
static int ext4_convert_unwritten_extents_endio(handle_t *handle, static int ext4_convert_unwritten_extents_endio(handle_t *handle,
struct inode *inode, struct inode *inode,
struct ext4_ext_path *path) struct ext4_ext_path *path)
...@@ -3047,46 +3073,27 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle, ...@@ -3047,46 +3073,27 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
struct ext4_extent_header *eh; struct ext4_extent_header *eh;
int depth; int depth;
int err = 0; int err = 0;
int ret = 0;
depth = ext_depth(inode); depth = ext_depth(inode);
eh = path[depth].p_hdr; eh = path[depth].p_hdr;
ex = path[depth].p_ext; ex = path[depth].p_ext;
ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical"
"block %llu, max_blocks %u\n", inode->i_ino,
(unsigned long long)le32_to_cpu(ex->ee_block),
ext4_ext_get_actual_len(ex));
err = ext4_ext_get_access(handle, inode, path + depth); err = ext4_ext_get_access(handle, inode, path + depth);
if (err) if (err)
goto out; goto out;
/* first mark the extent as initialized */ /* first mark the extent as initialized */
ext4_ext_mark_initialized(ex); ext4_ext_mark_initialized(ex);
/* /* note: ext4_ext_correct_indexes() isn't needed here because
* We have to see if it can be merged with the extent * borders are not changed
* on the left.
*/
if (ex > EXT_FIRST_EXTENT(eh)) {
/*
* To merge left, pass "ex - 1" to try_to_merge(),
* since it merges towards right _only_.
*/ */
ret = ext4_ext_try_to_merge(inode, path, ex - 1); ext4_ext_try_to_merge(inode, path, ex);
if (ret) {
err = ext4_ext_correct_indexes(handle, inode, path);
if (err)
goto out;
depth = ext_depth(inode);
ex--;
}
}
/*
* Try to Merge towards right.
*/
ret = ext4_ext_try_to_merge(inode, path, ex);
if (ret) {
err = ext4_ext_correct_indexes(handle, inode, path);
if (err)
goto out;
depth = ext_depth(inode);
}
/* Mark modified extent as dirty */ /* Mark modified extent as dirty */
err = ext4_ext_dirty(handle, inode, path + depth); err = ext4_ext_dirty(handle, inode, path + depth);
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment