[Ocfs2-tools-devel] [PATCH 3/6] abstract btree growing calls
Tao Ma
tao.ma at oracle.com
Mon Sep 24 02:20:16 PDT 2007
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: Tao Ma <tao.ma at oracle.com>
---
libocfs2/extend_file.c | 111 ++++++++++++++++++++++++++++-------------------
1 files changed, 66 insertions(+), 45 deletions(-)
diff --git a/libocfs2/extend_file.c b/libocfs2/extend_file.c
index 38f333f..c5f2d22 100644
--- a/libocfs2/extend_file.c
+++ b/libocfs2/extend_file.c
@@ -1356,7 +1356,9 @@ out_ret_path:
* copying all extent records from the dinode into the extent block,
* and then pointing the dinode to the new extent_block.
*/
-static errcode_t shift_tree_depth(struct insert_ctxt *ctxt, char **new_eb)
+static errcode_t shift_tree_depth(ocfs2_filesys *fs,
+ struct ocfs2_dinode *di,
+ char **new_eb)
{
errcode_t ret;
char *buf = NULL;
@@ -1365,19 +1367,19 @@ static errcode_t shift_tree_depth(struct insert_ctxt *ctxt, char **new_eb)
struct ocfs2_extent_list *el;
uint32_t new_clusters;
- el = &ctxt->di->id2.i_list;
+ el = &di->id2.i_list;
if (el->l_next_free_rec != el->l_count)
return OCFS2_ET_INTERNAL_FAILURE;
- ret = ocfs2_malloc_block(ctxt->fs->fs_io, &buf);
+ ret = ocfs2_malloc_block(fs->fs_io, &buf);
if (ret)
return ret;
- ret = ocfs2_new_extent_block(ctxt->fs, &blkno);
+ ret = ocfs2_new_extent_block(fs, &blkno);
if (ret)
goto out;
- ret = ocfs2_read_extent_block(ctxt->fs, blkno, buf);
+ ret = ocfs2_read_extent_block(fs, blkno, buf);
if (ret)
goto out;
@@ -1398,9 +1400,9 @@ static errcode_t shift_tree_depth(struct insert_ctxt *ctxt, char **new_eb)
el->l_next_free_rec = 1;
if (el->l_tree_depth == 1)
- ctxt->di->i_last_eb_blk = blkno;
+ di->i_last_eb_blk = blkno;
- ret = ocfs2_write_extent_block(ctxt->fs, blkno, buf);
+ ret = ocfs2_write_extent_block(fs, blkno, buf);
if (!ret)
*new_eb = buf;
out:
@@ -2095,16 +2097,68 @@ static void free_duplicated_extent_block_dinode(ocfs2_filesys *fs,
}
/*
+ * 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(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+ int *final_depth, char *last_eb)
+{
+ errcode_t ret;
+ char *eb_buf = NULL;
+ int shift;
+ int depth = di->id2.i_list.l_tree_depth;
+
+ shift = ocfs2_find_branch_target(fs, di, &eb_buf);
+ if (shift < 0) {
+ ret = shift;
+ 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) {
+
+ /* shift_tree_depth will return us a buffer with
+ * the new extent block (so we can pass that to
+ * ocfs2_add_branch). */
+ ret = shift_tree_depth(fs, di, &eb_buf);
+ if (ret)
+ goto out;
+
+ depth++;
+ /*
+ * Special case: we have room now if we shifted from
+ * tree_depth 0, so no more work needs to be done.
+ */
+ if (depth == 1)
+ goto out;
+ }
+
+ /* call ocfs2_add_branch to add the final part of the tree with
+ * the new data. */
+ ret = ocfs2_add_branch(fs, di, eb_buf, last_eb);
+
+out:
+ if (final_depth)
+ *final_depth = depth;
+ return ret;
+}
+
+/*
* Insert an extent into an inode btree.
*/
errcode_t ocfs2_insert_extent(ocfs2_filesys *fs, uint64_t ino, uint32_t cpos,
uint64_t c_blkno, uint32_t clusters)
{
errcode_t ret;
- int shift;
struct insert_ctxt ctxt;
struct ocfs2_insert_type insert = {0, };
- char *di_buf = NULL, *last_eb = NULL, *eb_buf = NULL;
+ char *di_buf = NULL, *last_eb = NULL;
char *backup_buf = NULL;
ret = ocfs2_malloc_block(fs->fs_io, &di_buf);
@@ -2154,44 +2208,13 @@ errcode_t ocfs2_insert_extent(ocfs2_filesys *fs, uint64_t ino, uint32_t cpos,
if (ret)
goto bail;
- /*
- * 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(fs, ctxt.di, &eb_buf);
- if (shift < 0) {
- ret = shift;
- 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) {
-
- /* shift_tree_depth will return us a buffer with
- * the new extent block (so we can pass that to
- * ocfs2_add_branch). */
- ret = shift_tree_depth(&ctxt, &eb_buf);
+ if (insert.ins_contig == CONTIG_NONE && insert.ins_free_records == 0) {
+ ret = ocfs2_grow_tree(fs, ctxt.di,
+ &insert.ins_tree_depth, last_eb);
if (ret)
goto bail;
-
- insert.ins_tree_depth++;
-
- 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. */
- ret = ocfs2_add_branch(ctxt.fs, ctxt.di, eb_buf, last_eb);
- if (ret)
- goto bail;
-
-out_add:
/* Finally, we can add clusters. This might rotate the tree for us. */
ret = ocfs2_do_insert_extent(&ctxt, &insert);
if (ret)
@@ -2212,8 +2235,6 @@ bail:
ocfs2_free(&backup_buf);
}
- if (eb_buf)
- ocfs2_free(&eb_buf);
if (last_eb)
ocfs2_free(&last_eb);
if (di_buf)
--
1.5.3.2.g4f337
More information about the Ocfs2-tools-devel
mailing list