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>
This commit is contained in:
parent
df5e622340
commit
197217a5af
@ -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
|
||||
* 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_extent *ex)
|
||||
{
|
||||
@ -1602,6 +1602,31 @@ static int ext4_ext_try_to_merge(struct inode *inode,
|
||||
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
|
||||
* existing extent.
|
||||
@ -3039,6 +3064,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
|
||||
ext4_ext_dirty(handle, inode, path + depth);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ext4_convert_unwritten_extents_endio(handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct ext4_ext_path *path)
|
||||
@ -3047,46 +3073,27 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
|
||||
struct ext4_extent_header *eh;
|
||||
int depth;
|
||||
int err = 0;
|
||||
int ret = 0;
|
||||
|
||||
depth = ext_depth(inode);
|
||||
eh = path[depth].p_hdr;
|
||||
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);
|
||||
if (err)
|
||||
goto out;
|
||||
/* first mark the extent as initialized */
|
||||
ext4_ext_mark_initialized(ex);
|
||||
|
||||
/*
|
||||
* We have to see if it can be merged with the extent
|
||||
* on the left.
|
||||
/* note: ext4_ext_correct_indexes() isn't needed here because
|
||||
* borders are not changed
|
||||
*/
|
||||
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);
|
||||
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);
|
||||
}
|
||||
ext4_ext_try_to_merge(inode, path, ex);
|
||||
|
||||
/* Mark modified extent as dirty */
|
||||
err = ext4_ext_dirty(handle, inode, path + depth);
|
||||
out:
|
||||
|
Loading…
Reference in New Issue
Block a user