[Ocfs2-tools-devel] [PATCH 2/6] libocfs2: extend xattr and xattr value tree

Tiger Yang tiger.yang at oracle.com
Wed Jul 29 00:01:29 PDT 2009


Add ocfs2_tree_extend_allocation and ocfs2_tree_insert_extent
for extending xattr record and xattr value tree.
On the other hand, use ocfs2_extend_allocation and
ocfs2_inode_insert_extent extend file data tree.

Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
---
 fswreck/extent.c                    |    4 +-
 include/ocfs2/ocfs2.h               |    9 +-
 libocfs2/extend_file.c              |  396 +++++++++++++++++++++++------------
 libocfs2/xattr.c                    |    3 +-
 tunefs.ocfs2/feature_sparse_files.c |    2 +-
 5 files changed, 276 insertions(+), 138 deletions(-)

diff --git a/fswreck/extent.c b/fswreck/extent.c
index e3fe020..2970cd9 100644
--- a/fswreck/extent.c
+++ b/fswreck/extent.c
@@ -103,8 +103,8 @@ static void custom_extend_allocation(ocfs2_filesys *fs, uint64_t ino,
 		 * we insert each cluster in reverse. */
 		for(i = n_clusters; i; --i) {
 			tmpblk = blkno + ocfs2_clusters_to_blocks(fs, i - 1);
-		 	ret = ocfs2_insert_extent(fs, ino, offset++,
-						  tmpblk, 1, 0);
+			ret = ocfs2_inode_insert_extent(fs, ino, offset++,
+							tmpblk, 1, 0);
 			if (ret) 
 				FSWRK_COM_FATAL(progname, ret);	
 		}
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 3c4195c..a171089 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -507,9 +507,9 @@ void ocfs2_init_group_desc(ocfs2_filesys *fs,
 errcode_t ocfs2_new_dir_block(ocfs2_filesys *fs, uint64_t dir_ino,
 			      uint64_t parent_ino, char **block);
 
-errcode_t ocfs2_insert_extent(ocfs2_filesys *fs, uint64_t ino, uint32_t cpos,
-			      uint64_t c_blkno, uint32_t clusters,
-			      uint16_t flag);
+errcode_t ocfs2_inode_insert_extent(ocfs2_filesys *fs, uint64_t ino,
+				    uint32_t cpos, uint64_t c_blkno,
+				    uint32_t clusters, uint16_t flag);
 errcode_t ocfs2_cached_inode_insert_extent(ocfs2_cached_inode *ci,
 					   uint32_t cpos, uint64_t c_blkno,
 					   uint32_t clusters, uint16_t flag);
@@ -1117,7 +1117,8 @@ errcode_t ocfs2_block_iterate_inode(ocfs2_filesys *fs,
 uint32_t ocfs2_xattr_uuid_hash(unsigned char *uuid);
 uint32_t ocfs2_xattr_name_hash(uint32_t uuid_hash, const char *name,
 			       int name_len);
-int ocfs2_xattr_find_leaf(ocfs2_filesys *fs, struct ocfs2_xattr_block *xb,
+int ocfs2_xattr_find_leaf(ocfs2_filesys *fs, struct ocfs2_extent_list *el,
+			  uint64_t el_blkno, char *el_blk,
 			  uint32_t cpos, char **leaf_buf);
 uint16_t ocfs2_xattr_buckets_per_cluster(ocfs2_filesys *fs);
 uint16_t ocfs2_blocks_per_xattr_bucket(ocfs2_filesys *fs);
diff --git a/libocfs2/extend_file.c b/libocfs2/extend_file.c
index a27b478..671f807 100644
--- a/libocfs2/extend_file.c
+++ b/libocfs2/extend_file.c
@@ -34,6 +34,8 @@
 #include <errno.h>
 #include <assert.h>
 #include "ocfs2/ocfs2.h"
+#include "xattr.h"
+#include "extent_tree.h"
 
 /*
  * Structures which describe a path through a btree, and functions to
@@ -452,7 +454,7 @@ static inline uint32_t ocfs2_sum_rightmost_rec(struct ocfs2_extent_list  *el)
  * contain a single record with e_clusters == 0.
  */
 static int ocfs2_add_branch(ocfs2_filesys *fs,
-			    struct ocfs2_dinode *fe,
+			    struct ocfs2_extent_tree *et,
 			    char *eb_buf,
 			    char **last_eb_buf)
 {
@@ -473,7 +475,7 @@ static int ocfs2_add_branch(ocfs2_filesys *fs,
 		eb = (struct ocfs2_extent_block *) eb_buf;
 		el = &eb->h_list;
 	} else
-		el = &fe->id2.i_list;
+		el = et->et_root_el;
 
 	/* we never add a branch to a leaf. */
 	assert(el->l_tree_depth);
@@ -560,7 +562,7 @@ static int ocfs2_add_branch(ocfs2_filesys *fs,
 	/* fe needs a new last extent block pointer, as does the
 	 * next_leaf on the previously last-extent-block.
 	 */
-	fe->i_last_eb_blk = new_last_eb_blk;
+	et->et_ops->eo_set_last_eb_blk(et, new_last_eb_blk);
 
 	/* here all the extent block and the new inode information should be
 	 * written back to the disk.
@@ -635,20 +637,17 @@ bail:
  * return status < 0 indicates an error.
  */
 static errcode_t ocfs2_find_branch_target(ocfs2_filesys *fs,
-					  struct ocfs2_dinode *fe,
+					  struct ocfs2_extent_list *el,
 					  char **target_buf)
 {
 	errcode_t ret = 0;
 	int i;
 	uint64_t blkno;
 	struct ocfs2_extent_block *eb;
-	struct ocfs2_extent_list  *el;
 	char *buf = NULL, *lowest_buf = NULL;
 
 	*target_buf = NULL;
 
-	el = &fe->id2.i_list;
-
 	ret = ocfs2_malloc_block(fs->fs_io, &buf);
 	if (ret)
 		return ret;
@@ -678,8 +677,7 @@ static errcode_t ocfs2_find_branch_target(ocfs2_filesys *fs,
 
 	/* If we didn't find one and the fe doesn't have any room,
 	 * then return '1' */
-	if (!lowest_buf
-	    && (fe->id2.i_list.l_next_free_rec == fe->id2.i_list.l_count))
+	if (!lowest_buf && el->l_next_free_rec == el->l_count)
 		ret = 1;
 
 	*target_buf = lowest_buf;
@@ -1027,27 +1025,37 @@ out:
 	return ret;
 }
 
-int ocfs2_xattr_find_leaf(ocfs2_filesys *fs, struct ocfs2_xattr_block *xb,
+static struct ocfs2_path *ocfs2_new_tree_path(struct ocfs2_extent_list *el,
+					       uint64_t el_blkno, char *el_blk)
+{
+	struct ocfs2_path *path = NULL;
+
+	if (ocfs2_malloc0(sizeof(*path), &path))
+		return NULL;
+
+	path->p_tree_depth = el->l_tree_depth;
+	path->p_node[0].blkno = el_blkno;
+	path->p_node[0].buf = el_blk;
+	path->p_node[0].el = el;
+
+	return path;
+}
+
+int ocfs2_xattr_find_leaf(ocfs2_filesys *fs, struct ocfs2_extent_list *el,
+			  uint64_t el_blkno, char *el_blk,
 			  uint32_t cpos, char **leaf_buf)
 {
 	int ret;
 	char *buf = NULL;
 	struct ocfs2_path *path = NULL;
-	struct ocfs2_extent_list *el = &xb->xb_attrs.xb_root.xt_list;
 
 	assert(el->l_tree_depth > 0);
 
-
-	ret = ocfs2_malloc0(sizeof(*path), &path);
+	path = ocfs2_new_tree_path(el, el_blkno, el_blk);
 
 	if (!path) {
 		ret = OCFS2_ET_NO_MEMORY;
 		goto out;
-	} else {
-		path->p_tree_depth = el->l_tree_depth;
-		path->p_node[0].blkno = xb->xb_blkno;
-		path->p_node[0].buf = (char *)xb;
-		path->p_node[0].el = el;
 	}
 
 	ret = ocfs2_find_path(fs, path, cpos);
@@ -2411,17 +2419,16 @@ static void ocfs2_subtract_from_rec(ocfs2_filesys *fs,
  * and then pointing the dinode to the new extent_block.
  */
 static errcode_t shift_tree_depth(ocfs2_filesys *fs,
-				  struct ocfs2_dinode *di,
+				  struct ocfs2_extent_tree *et,
 				  char **new_eb)
 {
 	errcode_t ret;
 	char *buf = NULL;
 	uint64_t blkno;
+	struct ocfs2_extent_list *el = et->et_root_el;
 	struct ocfs2_extent_block *eb;
-	struct ocfs2_extent_list *el;
 	uint32_t new_clusters;
 
-	el = &di->id2.i_list;
 	if (el->l_next_free_rec != el->l_count)
 		return OCFS2_ET_INTERNAL_FAILURE;
 
@@ -2454,7 +2461,7 @@ static errcode_t shift_tree_depth(ocfs2_filesys *fs,
 	el->l_next_free_rec = 1;
 
 	if (el->l_tree_depth == 1)
-		di->i_last_eb_blk = blkno;
+		et->et_ops->eo_set_last_eb_blk(et, blkno);
 
 	ret = ocfs2_write_extent_block(fs, blkno, buf);
 	if (!ret)
@@ -2574,68 +2581,21 @@ set_tail_append:
  * This computes a few things that are commonly used in the process of
  * inserting into the btree:
  *   - Whether the new extent is contiguous with an existing one.
- *   - The current tree depth.
  *   - Whether the insert is an appending one.
- *   - The total # of free records in the tree.
  *
  * All of the information is stored on the ocfs2_insert_type
  * structure.
  */
 static int ocfs2_figure_insert_type(struct insert_ctxt *ctxt,
-				    char **last_eb_buf,
-				    int *free_records,
+				    struct ocfs2_path *path,
+				    uint64_t last_eb_blk,
 				    struct ocfs2_insert_type *insert)
 {
 	int ret;
-	struct ocfs2_extent_block *eb;
-	struct ocfs2_extent_list *el;
-	struct ocfs2_dinode *di = ctxt->di;
 	struct ocfs2_extent_rec *insert_rec = &ctxt->rec;
 	ocfs2_filesys *fs = ctxt->fs;
-	struct ocfs2_path *path = NULL;
-	char *buf = *last_eb_buf;
-
-	insert->ins_split = SPLIT_NONE;
-
-	el = &di->id2.i_list;
-	insert->ins_tree_depth = el->l_tree_depth;
-
-	if (el->l_tree_depth) {
-		/*
-		 * If we have tree depth, we read in the
-		 * rightmost extent block ahead of time as
-		 * ocfs2_figure_insert_type() and ocfs2_add_branch()
-		 * may want it later.
-		 */
-		assert(buf);
-		ret = ocfs2_read_extent_block(fs, di->i_last_eb_blk, buf);
-		if (ret)
-			goto out;
-
-		eb = (struct ocfs2_extent_block *) buf;
-		el = &eb->h_list;
-	}
-	/*
-	 * Unless we have a contiguous insert, we'll need to know if
-	 * there is room left in our allocation tree for another
-	 * extent record.
-	 *
-	 * XXX: This test is simplistic, we can search for empty
-	 * extent records too.
-	 */
-	*free_records = el->l_count - el->l_next_free_rec;
-
-	if (!insert->ins_tree_depth) {
-		ocfs2_figure_contig_type(fs, insert, el, insert_rec);
-		ocfs2_figure_appending_type(insert, el, insert_rec);
-		return 0;
-	}
+	struct ocfs2_extent_list *el = NULL;
 
-	path = ocfs2_new_inode_path(fs, di);
-	if (!path) {
-		ret = OCFS2_ET_NO_MEMORY;
-		goto out;
-	}
 	/*
 	 * In the case that we're inserting past what the tree
 	 * currently accounts for, ocf2_find_path() will return for
@@ -2644,7 +2604,7 @@ static int ocfs2_figure_insert_type(struct insert_ctxt *ctxt,
 	 */
 	ret = ocfs2_find_path(fs, path, insert_rec->e_cpos);
 	if (ret)
-		goto out;
+		return ret;
 
 	el = path_leaf_el(path);
 
@@ -2677,7 +2637,7 @@ static int ocfs2_figure_insert_type(struct insert_ctxt *ctxt,
 	 * the case that we're doing a tail append, so maybe we can
 	 * take advantage of that information somehow.
 	 */
-	if (di->i_last_eb_blk == path_leaf_blkno(path)) {
+	if (last_eb_blk == path_leaf_blkno(path)) {
 		/*
 		 * Ok, ocfs2_find_path() returned us the rightmost
 		 * tree path. This might be an appending insert. There are
@@ -2689,9 +2649,6 @@ static int ocfs2_figure_insert_type(struct insert_ctxt *ctxt,
 		ocfs2_figure_appending_type(insert, el, insert_rec);
 	}
 
-out:
-	ocfs2_free_path(path);
-
 	return ret;
 }
 
@@ -2990,28 +2947,17 @@ out:
 	return ret;
 }
 
-static int ocfs2_do_insert_extent(struct insert_ctxt* ctxt,
-				  struct ocfs2_insert_type *type)
+static int __ocfs2_do_insert_extent(struct insert_ctxt *ctxt,
+				    struct ocfs2_insert_type *type,
+				    struct ocfs2_extent_list *el,
+				    struct ocfs2_path *right_path)
 {
-	int ret, rotate = 0;
+	int ret = 0;
+	int rotate = 0;
 	uint32_t cpos;
-	struct ocfs2_path *right_path = NULL;
 	struct ocfs2_path *left_path = NULL;
 	struct ocfs2_extent_rec *insert_rec = &ctxt->rec;
 	ocfs2_filesys *fs = ctxt->fs;
-	struct ocfs2_dinode *di = ctxt->di;
-	struct ocfs2_extent_list *el = &di->id2.i_list;
-
-	if (el->l_tree_depth == 0) {
-		ocfs2_insert_at_leaf(fs, insert_rec, el, type);
-		goto out_update_clusters;
-	}
-
-	right_path = ocfs2_new_inode_path(fs, di);
-	if (!right_path) {
-		ret = OCFS2_ET_NO_MEMORY;
-		goto out;
-	}
 
 	/*
 	 * Determine the path to start with. Rotations need the
@@ -3027,7 +2973,7 @@ static int ocfs2_do_insert_extent(struct insert_ctxt* ctxt,
 
 	ret = ocfs2_find_path(fs, right_path, cpos);
 	if (ret)
-		goto out;
+		return ret;
 
 	/*
 	 * Rotations and appends need special treatment - they modify
@@ -3042,33 +2988,52 @@ static int ocfs2_do_insert_extent(struct insert_ctxt* ctxt,
 	 * can wind up skipping both of these two special cases...
 	 */
 
-	if (rotate) {
+	if (rotate)
 		ret = ocfs2_rotate_tree_right(fs, type->ins_split,
 					      insert_rec->e_cpos,
 					      right_path, &left_path);
-		if (ret)
-			goto out;
-	} else if (type->ins_appending == APPEND_TAIL
-		   && type->ins_contig != CONTIG_LEFT) {
+	else if (type->ins_appending == APPEND_TAIL
+		 && type->ins_contig != CONTIG_LEFT)
 		ret = ocfs2_append_rec_to_path(fs, insert_rec,
 					       right_path, &left_path);
-		if (ret)
-			goto out;
- 	}
+	if (ret)
+		return ret;
 
 	ret = ocfs2_insert_path(ctxt, left_path, right_path, insert_rec, type);
+
+	ocfs2_free_path(left_path);
+
+	return ret;
+}
+
+static int ocfs2_inode_do_insert_extent(struct insert_ctxt *ctxt,
+					struct ocfs2_insert_type *type)
+{
+	int ret = 0;
+	struct ocfs2_path *right_path = NULL;
+	struct ocfs2_extent_rec *insert_rec = &ctxt->rec;
+	ocfs2_filesys *fs = ctxt->fs;
+	struct ocfs2_dinode *di = ctxt->di;
+	struct ocfs2_extent_list *el = &di->id2.i_list;
+
+	if (el->l_tree_depth == 0) {
+		ocfs2_insert_at_leaf(fs, insert_rec, el, type);
+		goto out_update_clusters;
+	}
+
+	right_path = ocfs2_new_inode_path(fs, di);
+	if (!right_path)
+		return OCFS2_ET_NO_MEMORY;
+
+	ret = __ocfs2_do_insert_extent(ctxt, type, el, right_path);
 	if (ret)
 		goto out;
 
 out_update_clusters:
 	if (type->ins_split == SPLIT_NONE)
 		di->i_clusters += insert_rec->e_leaf_clusters;
-	ret = 0;
-
 out:
-	ocfs2_free_path(left_path);
 	ocfs2_free_path(right_path);
-
 	return ret;
 }
 
@@ -3289,15 +3254,17 @@ static void free_duplicated_extent_block_dinode(ocfs2_filesys *fs,
  *
  * *last_eb will be updated by ocfs2_add_branch().
  */
-static int ocfs2_grow_tree(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+static int ocfs2_grow_tree(ocfs2_filesys *fs,
+			   struct ocfs2_extent_tree *et,
 			   int *final_depth, char **last_eb)
 {
 	errcode_t ret;
 	char *eb_buf = NULL;
 	int shift;
-	int depth = di->id2.i_list.l_tree_depth;
+	struct ocfs2_extent_list *el = et->et_root_el;
+	int depth = el->l_tree_depth;
 
-	shift = ocfs2_find_branch_target(fs, di, &eb_buf);
+	shift = ocfs2_find_branch_target(fs, el, &eb_buf);
 	if (shift < 0) {
 		ret = shift;
 		goto out;
@@ -3311,7 +3278,7 @@ static int ocfs2_grow_tree(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 		/* 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);
+		ret = shift_tree_depth(fs, et, &eb_buf);
 		if (ret)
 			goto out;
 
@@ -3332,7 +3299,7 @@ static int ocfs2_grow_tree(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 
 	/* 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);
+	ret = ocfs2_add_branch(fs, et, eb_buf, last_eb);
 
 out:
 	if (final_depth)
@@ -3343,9 +3310,9 @@ out:
 /*
  * 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,
-			      uint16_t flag)
+errcode_t ocfs2_inode_insert_extent(ocfs2_filesys *fs, uint64_t ino,
+				    uint32_t cpos, uint64_t c_blkno,
+				    uint32_t clusters, uint16_t flag)
 {
 	errcode_t ret;
 	ocfs2_cached_inode *ci = NULL;
@@ -3378,8 +3345,9 @@ errcode_t ocfs2_cached_inode_insert_extent(ocfs2_cached_inode *ci,
 	char *last_eb = NULL;
 	char *backup_buf = NULL;
 	char *di_buf = NULL;
-	int free_records = 0;
 	ocfs2_filesys *fs = ci->ci_fs;
+	struct ocfs2_extent_list *el = &ci->ci_inode->id2.i_list;
+	struct ocfs2_path *path = NULL;
 
 	ctxt.fs = fs;
 	ctxt.di = ci->ci_inode;
@@ -3393,7 +3361,7 @@ errcode_t ocfs2_cached_inode_insert_extent(ocfs2_cached_inode *ci,
 	 * And if the duplicate process fails, we should go on the normal
 	 * insert process.
 	 */
-	if (ctxt.di->id2.i_list.l_tree_depth) {
+	if (el->l_tree_depth) {
 		ret = ocfs2_malloc_block(fs->fs_io, &backup_buf);
 		if (ret)
 			goto bail;
@@ -3422,22 +3390,53 @@ errcode_t ocfs2_cached_inode_insert_extent(ocfs2_cached_inode *ci,
 	if (ret)
 		return ret;
 
-	ret = ocfs2_figure_insert_type(&ctxt, &last_eb, &free_records, &insert);
-	if (ret)
-		goto bail;
+	insert.ins_split = SPLIT_NONE;
+	insert.ins_tree_depth = el->l_tree_depth;
 
-	if (insert.ins_contig == CONTIG_NONE && free_records == 0) {
-		ret = ocfs2_grow_tree(fs, ctxt.di,
-				      &insert.ins_tree_depth, &last_eb);
+	if (!el->l_tree_depth) {
+		ocfs2_figure_contig_type(fs, &insert, el , &ctxt.rec);
+		ocfs2_figure_appending_type(&insert, el, &ctxt.rec);
+	} else {
+		/*
+		 * If we have tree depth, we read in the
+		 * rightmost extent block ahead of time as
+		 * ocfs2_figure_insert_type() and ocfs2_add_branch()
+		 * may want it later.
+		 */
+		ret = ocfs2_read_extent_block(fs, ctxt.di->i_last_eb_blk,
+					      last_eb);
 		if (ret)
 			goto bail;
+		el = &((struct ocfs2_extent_block *)last_eb)->h_list;
+
+		path = ocfs2_new_inode_path(fs, ctxt.di);
+		if (!path) {
+			ret = OCFS2_ET_NO_MEMORY;
+			goto bail;
+		}
+		ret = ocfs2_figure_insert_type(&ctxt, path,
+						ctxt.di->i_last_eb_blk,
+						&insert);
+		if (ret)
+			goto free_path;
+	}
+
+	if (insert.ins_contig == CONTIG_NONE &&
+	    el->l_count == el->l_next_free_rec) {
+		struct ocfs2_extent_tree et;
+
+		ocfs2_init_dinode_extent_tree(&et, fs, (char *)ci->ci_inode);
+		ret = ocfs2_grow_tree(fs, &et,
+				      &insert.ins_tree_depth, &last_eb);
+		if (ret)
+			goto free_path;
 	}
 
 	/* Finally, we can add clusters. This might rotate the tree for us. */
-	ret = ocfs2_do_insert_extent(&ctxt, &insert);
-	if (ret)
-		goto bail;
+	ret = ocfs2_inode_do_insert_extent(&ctxt, &insert);
 
+free_path:
+	ocfs2_free_path(path);
 bail:
 	if (backup_buf) {
 		/* we have duplicated the extent block during the insertion.
@@ -3507,7 +3506,11 @@ leftright:
 	}
 
 	if (rightmost_el->l_next_free_rec == rightmost_el->l_count) {
-		ret = ocfs2_grow_tree(ctxt->fs, ctxt->di, &depth, last_eb_buf);
+		struct ocfs2_extent_tree et;
+
+		ocfs2_init_dinode_extent_tree(&et, ctxt->fs, (char *)ctxt->di);
+		ret = ocfs2_grow_tree(ctxt->fs, &et,
+				      &depth, last_eb_buf);
 		if (ret)
 			goto out;
 	}
@@ -3540,7 +3543,7 @@ leftright:
 		do_leftright = 1;
 	}
 
-	ret = ocfs2_do_insert_extent(ctxt, &insert);
+	ret = ocfs2_inode_do_insert_extent(ctxt, &insert);
 	if (ret)
 		goto out;
 
@@ -3764,6 +3767,139 @@ out:
 	return ret;
 }
 
+errcode_t ocfs2_tree_insert_extent(ocfs2_cached_inode *ci,
+				   uint32_t cpos, uint64_t c_blkno,
+				   uint32_t clusters, uint16_t flag,
+				   struct ocfs2_extent_tree *et)
+{
+	errcode_t ret = 0;
+	struct insert_ctxt ctxt;
+	struct ocfs2_insert_type insert = {0, };
+	char *last_eb = NULL;
+	char *di_buf = NULL;
+	ocfs2_filesys *fs = ci->ci_fs;
+	struct ocfs2_extent_list *el = et->et_root_el;
+	struct ocfs2_path *path = NULL;
+
+	ctxt.fs = fs;
+	ctxt.di = ci->ci_inode;
+	di_buf = (char *)ctxt.di;
+
+	memset(&ctxt.rec, 0, sizeof(struct ocfs2_extent_rec));
+	ctxt.rec.e_cpos = cpos;
+	ctxt.rec.e_blkno = c_blkno;
+	ctxt.rec.e_leaf_clusters = clusters;
+	ctxt.rec.e_flags = flag;
+
+	insert.ins_split = SPLIT_NONE;
+	insert.ins_tree_depth = el->l_tree_depth;
+
+	if (!el->l_tree_depth) {
+		ocfs2_figure_contig_type(fs, &insert, el , &ctxt.rec);
+		ocfs2_figure_appending_type(&insert, el, &ctxt.rec);
+	} else {
+		/*
+		 * If we have tree depth, we read in the
+		 * rightmost extent block ahead of time as
+		 * ocfs2_figure_insert_type() and ocfs2_add_branch()
+		 * may want it later.
+		 */
+		uint64_t last_eb_blk = et->et_ops->eo_get_last_eb_blk(et);
+
+		ret = ocfs2_malloc_block(fs->fs_io, &last_eb);
+		if (ret)
+			return ret;
+		ret = ocfs2_read_extent_block(fs, last_eb_blk, last_eb);
+		if (ret)
+			goto bail;
+		el = &((struct ocfs2_extent_block *)last_eb)->h_list;
+
+		path = ocfs2_new_tree_path(el, last_eb_blk, last_eb);
+		if (!path) {
+			ret = OCFS2_ET_NO_MEMORY;
+			goto bail;
+		}
+		ret = ocfs2_figure_insert_type(&ctxt, path, last_eb_blk,
+						&insert);
+		if (ret)
+			goto free_path;
+	}
+
+	if (insert.ins_contig == CONTIG_NONE &&
+	    el->l_count == el->l_next_free_rec) {
+		ret = ocfs2_grow_tree(fs, et, &insert.ins_tree_depth,
+				      &last_eb);
+		if (ret)
+			goto free_path;
+	}
+
+	if (el->l_tree_depth == 0) {
+		ocfs2_insert_at_leaf(fs, &ctxt.rec, el, &insert);
+		goto out_update_clusters;
+	}
+
+	/* Finally, we can add clusters. This might rotate the tree for us. */
+	ret = __ocfs2_do_insert_extent(&ctxt, &insert, el, path);
+	if (ret)
+		goto free_path;
+
+out_update_clusters:
+	if (insert.ins_split == SPLIT_NONE)
+		et->et_ops->eo_update_clusters(et, ctxt.rec.e_leaf_clusters);
+	ret = 0;
+
+free_path:
+	ocfs2_free_path(path);
+bail:
+
+	if (last_eb)
+		ocfs2_free(&last_eb);
+
+	return ret;
+}
+
+errcode_t ocfs2_tree_extend_allocation(ocfs2_cached_inode *ci,
+					uint32_t new_clusters,
+					struct ocfs2_extent_tree *et)
+{
+	ocfs2_filesys *fs = ci->ci_fs;
+	errcode_t ret = 0;
+	uint32_t n_clusters = 0, cpos;
+	uint64_t blkno;
+	char *buf = NULL;
+
+	if (!(fs->fs_flags & OCFS2_FLAG_RW))
+		return OCFS2_ET_RO_FILESYS;
+
+	cpos = et->et_ops->eo_get_clusters(et);
+	while (new_clusters) {
+		n_clusters = 1;
+		ret = ocfs2_new_clusters(fs, 1, new_clusters, &blkno,
+					 &n_clusters);
+		if (ret)
+			break;
+
+		ret = ocfs2_tree_insert_extent(ci, cpos, blkno,
+						n_clusters, 0, et);
+		if (ret) {
+			/* XXX: We don't wan't to overwrite the error
+			 * from insert_extent().  But we probably need
+			 * to BE LOUDLY UPSET. */
+			ocfs2_free_clusters(fs, n_clusters, blkno);
+			goto out_free_buf;
+		}
+
+		new_clusters -= n_clusters;
+		cpos += n_clusters;
+	}
+
+out_free_buf:
+	if (buf)
+		ocfs2_free(&buf);
+	return ret;
+}
+
+
 errcode_t ocfs2_extend_allocation(ocfs2_filesys *fs, uint64_t ino,
 				  uint32_t new_clusters)
 {
@@ -3795,8 +3931,8 @@ errcode_t ocfs2_extend_allocation(ocfs2_filesys *fs, uint64_t ino,
 		if (ret)
 			break;
 
-		ret = ocfs2_insert_extent(fs, ino, cpos, blkno, n_clusters,
-					  0);
+		ret = ocfs2_inode_insert_extent(fs, ino, cpos, blkno,
+						n_clusters, 0);
 		if (ret) {
 			/* XXX: We don't wan't to overwrite the error
 			 * from insert_extent().  But we probably need
diff --git a/libocfs2/xattr.c b/libocfs2/xattr.c
index d217ff0..c6f69c4 100644
--- a/libocfs2/xattr.c
+++ b/libocfs2/xattr.c
@@ -288,7 +288,8 @@ errcode_t ocfs2_xattr_get_rec(ocfs2_filesys *fs,
 		return OCFS2_ET_INVALID_ARGUMENT;
 
 	if (el->l_tree_depth) {
-		ret = ocfs2_xattr_find_leaf(fs, xb, name_hash, &eb_buf);
+		ret = ocfs2_xattr_find_leaf(fs, el, xb->xb_blkno, (char *)xb,
+					    name_hash, &eb_buf);
 		if (ret)
 			goto out;
 
diff --git a/tunefs.ocfs2/feature_sparse_files.c b/tunefs.ocfs2/feature_sparse_files.c
index ddb966f..f0dcea6 100644
--- a/tunefs.ocfs2/feature_sparse_files.c
+++ b/tunefs.ocfs2/feature_sparse_files.c
@@ -395,7 +395,7 @@ static errcode_t fill_one_hole(ocfs2_filesys *fs, struct sparse_file *file,
 		if (ret)
 			break;
 
-		ret = ocfs2_insert_extent(fs, file->blkno,
+		ret = ocfs2_inode_insert_extent(fs, file->blkno,
 					  start, p_start,
 					  n_clusters, 0);
 		if (ret)
-- 
1.5.4.1




More information about the Ocfs2-tools-devel mailing list