ocfs2: Enable cross extent block merge.

In ocfs2_figure_merge_contig_type, we judge whether there exists
a cross extent block merge and enable it by setting CONTIG_LEFT
and CONTIG_RIGHT accordingly.

Signed-off-by: Tao Ma <tao.ma@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
This commit is contained in:
Tao Ma 2008-01-30 14:21:32 +08:00 committed by Mark Fasheh
parent 677b975282
commit ad5a4d7093

View File

@ -3782,20 +3782,57 @@ out:
} }
static enum ocfs2_contig_type static enum ocfs2_contig_type
ocfs2_figure_merge_contig_type(struct inode *inode, ocfs2_figure_merge_contig_type(struct inode *inode, struct ocfs2_path *path,
struct ocfs2_extent_list *el, int index, struct ocfs2_extent_list *el, int index,
struct ocfs2_extent_rec *split_rec) struct ocfs2_extent_rec *split_rec)
{ {
struct ocfs2_extent_rec *rec; int status;
enum ocfs2_contig_type ret = CONTIG_NONE; enum ocfs2_contig_type ret = CONTIG_NONE;
u32 left_cpos, right_cpos;
struct ocfs2_extent_rec *rec = NULL;
struct ocfs2_extent_list *new_el;
struct ocfs2_path *left_path = NULL, *right_path = NULL;
struct buffer_head *bh;
struct ocfs2_extent_block *eb;
if (index > 0) {
rec = &el->l_recs[index - 1];
} else if (path->p_tree_depth > 0) {
status = ocfs2_find_cpos_for_left_leaf(inode->i_sb,
path, &left_cpos);
if (status)
goto out;
if (left_cpos != 0) {
left_path = ocfs2_new_path(path_root_bh(path),
path_root_el(path));
if (!left_path)
goto out;
status = ocfs2_find_path(inode, left_path, left_cpos);
if (status)
goto out;
new_el = path_leaf_el(left_path);
if (le16_to_cpu(new_el->l_next_free_rec) !=
le16_to_cpu(new_el->l_count)) {
bh = path_leaf_bh(left_path);
eb = (struct ocfs2_extent_block *)bh->b_data;
OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
eb);
goto out;
}
rec = &new_el->l_recs[
le16_to_cpu(new_el->l_next_free_rec) - 1];
}
}
/* /*
* We're careful to check for an empty extent record here - * We're careful to check for an empty extent record here -
* the merge code will know what to do if it sees one. * the merge code will know what to do if it sees one.
*/ */
if (rec) {
if (index > 0) {
rec = &el->l_recs[index - 1];
if (index == 1 && ocfs2_is_empty_extent(rec)) { if (index == 1 && ocfs2_is_empty_extent(rec)) {
if (split_rec->e_cpos == el->l_recs[index].e_cpos) if (split_rec->e_cpos == el->l_recs[index].e_cpos)
ret = CONTIG_RIGHT; ret = CONTIG_RIGHT;
@ -3804,10 +3841,45 @@ ocfs2_figure_merge_contig_type(struct inode *inode,
} }
} }
if (index < (le16_to_cpu(el->l_next_free_rec) - 1)) { rec = NULL;
if (index < (le16_to_cpu(el->l_next_free_rec) - 1))
rec = &el->l_recs[index + 1];
else if (le16_to_cpu(el->l_next_free_rec) == le16_to_cpu(el->l_count) &&
path->p_tree_depth > 0) {
status = ocfs2_find_cpos_for_right_leaf(inode->i_sb,
path, &right_cpos);
if (status)
goto out;
if (right_cpos == 0)
goto out;
right_path = ocfs2_new_path(path_root_bh(path),
path_root_el(path));
if (!right_path)
goto out;
status = ocfs2_find_path(inode, right_path, right_cpos);
if (status)
goto out;
new_el = path_leaf_el(right_path);
rec = &new_el->l_recs[0];
if (ocfs2_is_empty_extent(rec)) {
if (le16_to_cpu(new_el->l_next_free_rec) <= 1) {
bh = path_leaf_bh(right_path);
eb = (struct ocfs2_extent_block *)bh->b_data;
OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb,
eb);
goto out;
}
rec = &new_el->l_recs[1];
}
}
if (rec) {
enum ocfs2_contig_type contig_type; enum ocfs2_contig_type contig_type;
rec = &el->l_recs[index + 1];
contig_type = ocfs2_extent_contig(inode, rec, split_rec); contig_type = ocfs2_extent_contig(inode, rec, split_rec);
if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT) if (contig_type == CONTIG_LEFT && ret == CONTIG_RIGHT)
@ -3816,6 +3888,12 @@ ocfs2_figure_merge_contig_type(struct inode *inode,
ret = contig_type; ret = contig_type;
} }
out:
if (left_path)
ocfs2_free_path(left_path);
if (right_path)
ocfs2_free_path(right_path);
return ret; return ret;
} }
@ -4278,7 +4356,7 @@ static int __ocfs2_mark_extent_written(struct inode *inode,
goto out; goto out;
} }
ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, el, ctxt.c_contig_type = ocfs2_figure_merge_contig_type(inode, path, el,
split_index, split_index,
split_rec); split_rec);