ocfs2: abstract btree growing calls
The top level calls and logic for growing a tree can easily be abstracted out of ocfs2_insert_extent() into a seperate function - ocfs2_grow_tree(). This allows future code to easily grow btrees when needed. Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
This commit is contained in:
119
fs/ocfs2/alloc.c
119
fs/ocfs2/alloc.c
@@ -824,6 +824,74 @@ bail:
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grow a b-tree so that it has more records.
|
||||||
|
*
|
||||||
|
* We might shift the tree depth in which case existing paths should
|
||||||
|
* be considered invalid.
|
||||||
|
*
|
||||||
|
* Tree depth after the grow is returned via *final_depth.
|
||||||
|
*/
|
||||||
|
static int ocfs2_grow_tree(struct inode *inode, handle_t *handle,
|
||||||
|
struct buffer_head *di_bh, int *final_depth,
|
||||||
|
struct buffer_head *last_eb_bh,
|
||||||
|
struct ocfs2_alloc_context *meta_ac)
|
||||||
|
{
|
||||||
|
int ret, shift;
|
||||||
|
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
|
||||||
|
int depth = le16_to_cpu(di->id2.i_list.l_tree_depth);
|
||||||
|
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
||||||
|
struct buffer_head *bh = NULL;
|
||||||
|
|
||||||
|
BUG_ON(meta_ac == NULL);
|
||||||
|
|
||||||
|
shift = ocfs2_find_branch_target(osb, inode, di_bh, &bh);
|
||||||
|
if (shift < 0) {
|
||||||
|
ret = shift;
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We traveled all the way to the bottom of the allocation tree
|
||||||
|
* and didn't find room for any more extents - we need to add
|
||||||
|
* another tree level */
|
||||||
|
if (shift) {
|
||||||
|
BUG_ON(bh);
|
||||||
|
mlog(0, "need to shift tree depth (current = %d)\n", depth);
|
||||||
|
|
||||||
|
/* ocfs2_shift_tree_depth will return us a buffer with
|
||||||
|
* the new extent block (so we can pass that to
|
||||||
|
* ocfs2_add_branch). */
|
||||||
|
ret = ocfs2_shift_tree_depth(osb, handle, inode, di_bh,
|
||||||
|
meta_ac, &bh);
|
||||||
|
if (ret < 0) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
depth++;
|
||||||
|
/* Special case: we have room now if we shifted from
|
||||||
|
* tree_depth 0 */
|
||||||
|
if (depth == 1)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* call ocfs2_add_branch to add the final part of the tree with
|
||||||
|
* the new data. */
|
||||||
|
mlog(0, "add branch. bh = %p\n", bh);
|
||||||
|
ret = ocfs2_add_branch(osb, handle, inode, di_bh, bh, last_eb_bh,
|
||||||
|
meta_ac);
|
||||||
|
if (ret < 0) {
|
||||||
|
mlog_errno(ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (final_depth)
|
||||||
|
*final_depth = depth;
|
||||||
|
brelse(bh);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is only valid for leaf nodes, which are the only ones that can
|
* This is only valid for leaf nodes, which are the only ones that can
|
||||||
* have empty extents anyway.
|
* have empty extents anyway.
|
||||||
@@ -2325,7 +2393,7 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
|
|||||||
u32 new_clusters,
|
u32 new_clusters,
|
||||||
struct ocfs2_alloc_context *meta_ac)
|
struct ocfs2_alloc_context *meta_ac)
|
||||||
{
|
{
|
||||||
int status, shift;
|
int status;
|
||||||
struct buffer_head *last_eb_bh = NULL;
|
struct buffer_head *last_eb_bh = NULL;
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
struct ocfs2_insert_type insert = {0, };
|
struct ocfs2_insert_type insert = {0, };
|
||||||
@@ -2360,55 +2428,16 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
|
|||||||
insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
|
insert.ins_appending, insert.ins_contig, insert.ins_contig_index,
|
||||||
insert.ins_free_records, insert.ins_tree_depth);
|
insert.ins_free_records, insert.ins_tree_depth);
|
||||||
|
|
||||||
/*
|
if (insert.ins_contig == CONTIG_NONE && insert.ins_free_records == 0) {
|
||||||
* Avoid growing the tree unless we're out of records and the
|
status = ocfs2_grow_tree(inode, handle, fe_bh,
|
||||||
* insert type requres one.
|
&insert.ins_tree_depth, last_eb_bh,
|
||||||
*/
|
|
||||||
if (insert.ins_contig != CONTIG_NONE || insert.ins_free_records)
|
|
||||||
goto out_add;
|
|
||||||
|
|
||||||
shift = ocfs2_find_branch_target(osb, inode, fe_bh, &bh);
|
|
||||||
if (shift < 0) {
|
|
||||||
status = shift;
|
|
||||||
mlog_errno(status);
|
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We traveled all the way to the bottom of the allocation tree
|
|
||||||
* and didn't find room for any more extents - we need to add
|
|
||||||
* another tree level */
|
|
||||||
if (shift) {
|
|
||||||
BUG_ON(bh);
|
|
||||||
mlog(0, "need to shift tree depth "
|
|
||||||
"(current = %d)\n", insert.ins_tree_depth);
|
|
||||||
|
|
||||||
/* ocfs2_shift_tree_depth will return us a buffer with
|
|
||||||
* the new extent block (so we can pass that to
|
|
||||||
* ocfs2_add_branch). */
|
|
||||||
status = ocfs2_shift_tree_depth(osb, handle, inode, fe_bh,
|
|
||||||
meta_ac, &bh);
|
|
||||||
if (status < 0) {
|
|
||||||
mlog_errno(status);
|
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
insert.ins_tree_depth++;
|
|
||||||
/* Special case: we have room now if we shifted from
|
|
||||||
* tree_depth 0 */
|
|
||||||
if (insert.ins_tree_depth == 1)
|
|
||||||
goto out_add;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* call ocfs2_add_branch to add the final part of the tree with
|
|
||||||
* the new data. */
|
|
||||||
mlog(0, "add branch. bh = %p\n", bh);
|
|
||||||
status = ocfs2_add_branch(osb, handle, inode, fe_bh, bh, last_eb_bh,
|
|
||||||
meta_ac);
|
meta_ac);
|
||||||
if (status < 0) {
|
if (status) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out_add:
|
|
||||||
/* Finally, we can add clusters. This might rotate the tree for us. */
|
/* Finally, we can add clusters. This might rotate the tree for us. */
|
||||||
status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
|
status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
|
Reference in New Issue
Block a user