mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-02 00:24:12 +08:00
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:
parent
1f6697d072
commit
c3afcbb344
119
fs/ocfs2/alloc.c
119
fs/ocfs2/alloc.c
@ -824,6 +824,74 @@ bail:
|
||||
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
|
||||
* have empty extents anyway.
|
||||
@ -2325,7 +2393,7 @@ int ocfs2_insert_extent(struct ocfs2_super *osb,
|
||||
u32 new_clusters,
|
||||
struct ocfs2_alloc_context *meta_ac)
|
||||
{
|
||||
int status, shift;
|
||||
int status;
|
||||
struct buffer_head *last_eb_bh = NULL;
|
||||
struct buffer_head *bh = NULL;
|
||||
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_free_records, insert.ins_tree_depth);
|
||||
|
||||
/*
|
||||
* Avoid growing the tree unless we're out of records and the
|
||||
* insert type requres one.
|
||||
*/
|
||||
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) {
|
||||
if (insert.ins_contig == CONTIG_NONE && insert.ins_free_records == 0) {
|
||||
status = ocfs2_grow_tree(inode, handle, fe_bh,
|
||||
&insert.ins_tree_depth, last_eb_bh,
|
||||
meta_ac);
|
||||
if (status) {
|
||||
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);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
out_add:
|
||||
/* Finally, we can add clusters. This might rotate the tree for us. */
|
||||
status = ocfs2_do_insert_extent(inode, handle, fe_bh, &rec, &insert);
|
||||
if (status < 0)
|
||||
|
Loading…
Reference in New Issue
Block a user