[Ocfs2-tools-devel] [PATCH 06/10] libocfs2: Add ocfs2_tree_insert_extent.

Tao Ma tao.ma at oracle.com
Wed Sep 30 07:27:43 PDT 2009


Now ocfs2_inode_insert_extent use extent tree based b-tree
functions, but other extent tree users all need some similar
function, so a new function named ocfs2_tree_insert_extent
is added and inode insert will use it. We also change the
old duplicate_extent_block_inode to extent_tree based, so
that we can save up our b-tree in case of insert fails.
And we also move ocfs2_inode_insert_extent into extend_file.c
since it is inode related.

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 libocfs2/extend_file.c |   41 ++++++++++++++
 libocfs2/extent_tree.c |  139 +++++++++++++++++++++--------------------------
 libocfs2/extent_tree.h |    4 ++
 3 files changed, 107 insertions(+), 77 deletions(-)

diff --git a/libocfs2/extend_file.c b/libocfs2/extend_file.c
index d12cb9f..8d157bc 100644
--- a/libocfs2/extend_file.c
+++ b/libocfs2/extend_file.c
@@ -34,7 +34,48 @@
 #include <errno.h>
 #include <assert.h>
 #include "ocfs2/ocfs2.h"
+#include "extent_tree.h"
 
+/*
+ * Insert an extent into an inode btree.
+ */
+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;
+
+	ret = ocfs2_read_cached_inode(fs, ino, &ci);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_cached_inode_insert_extent(ci, cpos, c_blkno,
+					       clusters, flag);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_write_cached_inode(fs, ci);
+
+bail:
+	if (ci)
+		ocfs2_free_cached_inode(fs, ci);
+
+	return ret;
+}
+
+errcode_t ocfs2_cached_inode_insert_extent(ocfs2_cached_inode *ci,
+					   uint32_t cpos, uint64_t c_blkno,
+					   uint32_t clusters, uint16_t flag)
+{
+	struct ocfs2_extent_tree et;
+
+	ocfs2_init_dinode_extent_tree(&et, ci->ci_fs, (char *)ci->ci_inode,
+				      ci->ci_inode->i_blkno);
+
+	return ocfs2_tree_insert_extent(ci->ci_fs, &et, cpos, c_blkno,
+					clusters, flag);
+}
 
 errcode_t ocfs2_cached_inode_extend_allocation(ocfs2_cached_inode *ci,
 					       uint32_t new_clusters)
diff --git a/libocfs2/extent_tree.c b/libocfs2/extent_tree.c
index c3b6428..36f96df 100644
--- a/libocfs2/extent_tree.c
+++ b/libocfs2/extent_tree.c
@@ -715,7 +715,7 @@ bail:
  * return status < 0 indicates an error.
  */
 static errcode_t ocfs2_find_branch_target(ocfs2_filesys *fs,
-					  struct ocfs2_extent_list *el,
+					  struct ocfs2_extent_tree *et,
 					  char **target_buf)
 {
 	errcode_t ret = 0;
@@ -723,6 +723,7 @@ static errcode_t ocfs2_find_branch_target(ocfs2_filesys *fs,
 	uint64_t blkno;
 	struct ocfs2_extent_block *eb;
 	char *buf = NULL, *lowest_buf = NULL;
+	struct ocfs2_extent_list *el = et->et_root_el;
 
 	*target_buf = NULL;
 
@@ -753,6 +754,7 @@ static errcode_t ocfs2_find_branch_target(ocfs2_filesys *fs,
 			lowest_buf = buf;
 	}
 
+	el = et->et_root_el;
 	/* If we didn't find one and the fe doesn't have any room,
 	 * then return '1' */
 	if (!lowest_buf && el->l_next_free_rec == el->l_count)
@@ -3109,7 +3111,7 @@ out:
 }
 
 struct duplicate_ctxt {
-	struct ocfs2_dinode *di;
+	struct ocfs2_extent_tree *et;
 	uint64_t next_leaf_blk;
 };
 
@@ -3210,8 +3212,8 @@ static errcode_t duplicate_extent_block(ocfs2_filesys *fs,
 
 		eb = (struct ocfs2_extent_block *)new_eb_buf;
 		/* set the new i_last_eb_blk in the new dinode. */
-		if (ctxt->di->i_last_eb_blk == blkno)
-			ctxt->di->i_last_eb_blk = new_blkno;
+		if (ocfs2_et_get_last_eb_blk(ctxt->et) == blkno)
+			ocfs2_et_set_last_eb_blk(ctxt->et, new_blkno);
 	}
 
 	new_el->l_next_free_rec = old_el->l_next_free_rec;
@@ -3234,18 +3236,23 @@ bail:
 	return ret;
 }
 
-static errcode_t duplicate_extent_block_dinode(ocfs2_filesys *fs,
-					       char *old_buf, char *new_buf)
+static errcode_t duplicate_extent_block_et(ocfs2_filesys *fs,
+					   struct ocfs2_extent_tree *et)
 {
 	errcode_t ret = 0;
-	struct ocfs2_dinode *old_di = NULL, *new_di = NULL;
 	struct ocfs2_extent_list *old_el = NULL, *new_el = NULL;
+	char *old_buf, *new_buf;
 	struct duplicate_ctxt ctxt;
 
-	old_di = (struct ocfs2_dinode *)old_buf;
-	old_el = &old_di->id2.i_list;
-	new_di = (struct ocfs2_dinode *)new_buf;
-	new_el = &new_di->id2.i_list;
+	ret = ocfs2_malloc_block(fs->fs_io, &old_buf);
+	if (ret)
+		return ret;
+
+	memcpy(old_buf, et->et_root_buf, fs->fs_blocksize);
+	new_buf = et->et_root_buf;
+	new_el = et->et_root_el;
+	old_el = (struct ocfs2_extent_list *)
+			(old_buf + ((char *)new_el - new_buf));
 
 	assert(old_el->l_tree_depth > 0);
 
@@ -3256,10 +3263,11 @@ static errcode_t duplicate_extent_block_dinode(ocfs2_filesys *fs,
 	new_el->l_next_free_rec = 0;
 
 	memset(&ctxt, 0, sizeof(ctxt));
-	ctxt.di = new_di;
+	ctxt.et = et;
 	ctxt.next_leaf_blk = 0;
 	ret = duplicate_extent_block(fs, old_el, new_el, &ctxt);
 
+	ocfs2_free(&old_buf);
 	return ret;
 }
 
@@ -3301,20 +3309,6 @@ static void free_duplicated_extent_block(ocfs2_filesys *fs,
 		ocfs2_free(&buf);
 }
 
-static void free_duplicated_extent_block_dinode(ocfs2_filesys *fs,
-						char *di_buf)
-{
-	struct ocfs2_dinode *di = NULL;
-	struct ocfs2_extent_list *el = NULL;
-
-	di = (struct ocfs2_dinode *)di_buf;
-	el = &di->id2.i_list;
-
-	assert(el->l_tree_depth > 0);
-
-	free_duplicated_extent_block(fs, el);
-}
-
 /*
  * Grow a b-tree so that it has more records.
  *
@@ -3335,7 +3329,7 @@ static int ocfs2_grow_tree(ocfs2_filesys *fs,
 	struct ocfs2_extent_list *el = et->et_root_el;
 	int depth = el->l_tree_depth;
 
-	shift = ocfs2_find_branch_target(fs, el, &eb_buf);
+	shift = ocfs2_find_branch_target(fs, et, &eb_buf);
 	if (shift < 0) {
 		ret = shift;
 		goto out;
@@ -3378,76 +3372,44 @@ out:
 	return ret;
 }
 
-/*
- * Insert an extent into an inode btree.
- */
-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;
-
-	ret = ocfs2_read_cached_inode(fs, ino, &ci);
-	if (ret)
-		goto bail;
-
-	ret = ocfs2_cached_inode_insert_extent(ci, cpos, c_blkno,
-					       clusters, flag);
-	if (ret)
-		goto bail;
-
-	ret = ocfs2_write_cached_inode(fs, ci);
-
-bail:
-	if (ci)
-		ocfs2_free_cached_inode(fs, ci);
-
-	return ret;
-}
-
-errcode_t ocfs2_cached_inode_insert_extent(ocfs2_cached_inode *ci,
-					   uint32_t cpos, uint64_t c_blkno,
-					   uint32_t clusters, uint16_t flag)
+errcode_t ocfs2_tree_insert_extent(ocfs2_filesys *fs,
+				   struct ocfs2_extent_tree *et,
+				   uint32_t cpos, uint64_t c_blkno,
+				   uint32_t clusters, uint16_t flag)
 {
 	errcode_t ret;
 	struct insert_ctxt ctxt;
 	struct ocfs2_insert_type insert = {0, };
 	char *last_eb = NULL;
 	char *backup_buf = NULL;
-	char *di_buf = NULL;
+	char *root_buf = et->et_root_buf;
 	int free_records = 0;
-	ocfs2_filesys *fs = ci->ci_fs;
-	struct ocfs2_extent_tree et;
 
-	ocfs2_init_dinode_extent_tree(&et, fs, (char *)ci->ci_inode,
-				      ci->ci_inode->i_blkno);
 	ctxt.fs = fs;
-	ctxt.et = &et;
-	di_buf = (char *)ci->ci_inode;
+	ctxt.et = et;
 
 	/* In order to orderize the written block sequence and avoid
-	 * the corruption for the inode, we duplicate the extent block
+	 * the corruption for the b-tree, we duplicate the extent block
 	 * here and do the insertion in the duplicated ones.
 	 *
-	 * Note: we only do this in case the file has extent blocks.
+	 * Note: we only do this in case the b-tree has extent blocks.
 	 * And if the duplicate process fails, we should go on the normal
 	 * insert process.
 	 */
-	if (ci->ci_inode->id2.i_list.l_tree_depth) {
+	if (et->et_root_el->l_tree_depth) {
 		ret = ocfs2_malloc_block(fs->fs_io, &backup_buf);
 		if (ret)
 			goto bail;
 
-		memcpy(backup_buf, di_buf, fs->fs_blocksize);
+		memcpy(backup_buf, root_buf, fs->fs_blocksize);
 
 		/* duplicate the extent block. If it succeeds, di_buf
 		 * will point to the new allocated extent blocks, and
 		 * the following insertion will happens to the new ones.
 		 */
-		ret = duplicate_extent_block_dinode(fs, backup_buf, di_buf);
+		ret = duplicate_extent_block_et(fs, et);
 		if (ret) {
-			memcpy(di_buf, backup_buf,fs->fs_blocksize);
+			memcpy(root_buf, backup_buf, fs->fs_blocksize);
 			ocfs2_free(&backup_buf);
 			backup_buf = NULL;
 		}
@@ -3481,20 +3443,35 @@ errcode_t ocfs2_cached_inode_insert_extent(ocfs2_cached_inode *ci,
 
 bail:
 	if (backup_buf) {
+		struct ocfs2_extent_list *free_el;
+		int offset = (char *)et->et_root_el - et->et_root_buf;
 		/* we have duplicated the extent block during the insertion.
 		 * so if it succeeds, we should free the old ones, and if fails,
 		 * the duplicate ones should be freed.
 		 */
+
 		if (ret)
-			free_duplicated_extent_block_dinode(fs, di_buf);
+			free_el = (struct ocfs2_extent_list *)
+						(et->et_root_buf + offset);
 		else
-			free_duplicated_extent_block_dinode(fs, backup_buf);
+			free_el = (struct ocfs2_extent_list *)
+						(backup_buf + offset);
+
+		free_duplicated_extent_block(fs, free_el);
 		ocfs2_free(&backup_buf);
 	}
 
 	if (last_eb)
 		ocfs2_free(&last_eb);
 
+	/*
+	 * Write the root buffer here.
+	 * If the caller don't initialize the write function, it should
+	 * be responsible for write the root buffer.
+	 */
+	if (!ret && et->et_root_write)
+		ret = et->et_root_write(fs, et->et_root_blkno, root_buf);
+
 	return ret;
 }
 
@@ -3727,6 +3704,8 @@ int ocfs2_mark_extent_written(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 	if (!ocfs2_writes_unwritten_extents(OCFS2_RAW_SB(fs->fs_super)))
 		return OCFS2_ET_UNSUPP_FEATURE;
 
+	ocfs2_init_dinode_extent_tree(&et, fs, (char *)di, di->i_blkno);
+
 	/* In order to orderize the written block sequence and avoid
 	 * the corruption for the inode, we duplicate the extent block
 	 * here and do the insertion in the duplicated ones.
@@ -3747,7 +3726,7 @@ int ocfs2_mark_extent_written(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 		 * will point to the new allocated extent blocks, and
 		 * the following insertion will happens to the new ones.
 		 */
-		ret = duplicate_extent_block_dinode(fs, backup_buf, di_buf);
+		ret = duplicate_extent_block_et(fs, &et);
 		if (ret) {
 			memcpy(di_buf, backup_buf,fs->fs_blocksize);
 			ocfs2_free(&backup_buf);
@@ -3774,7 +3753,6 @@ int ocfs2_mark_extent_written(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 	}
 
 	ctxt.fs = fs;
-	ocfs2_init_dinode_extent_tree(&et, fs, (char *)di, di->i_blkno);
 	ctxt.et = &et;
 
 	memset(&ctxt.rec, 0, sizeof(struct ocfs2_extent_rec));
@@ -3792,14 +3770,21 @@ int ocfs2_mark_extent_written(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 
 out:
 	if (backup_buf) {
+		struct ocfs2_extent_list *free_el;
+		int offset = (char *)et.et_root_el - et.et_root_buf;
 		/* we have duplicated the extent block during the insertion.
 		 * so if it succeeds, we should free the old ones, and if fails,
 		 * the duplicate ones should be freed.
 		 */
+
 		if (ret)
-			free_duplicated_extent_block_dinode(fs, di_buf);
+			free_el = (struct ocfs2_extent_list *)
+						(di_buf + offset);
 		else
-			free_duplicated_extent_block_dinode(fs, backup_buf);
+			free_el = (struct ocfs2_extent_list *)
+						(backup_buf + offset);
+
+		free_duplicated_extent_block(fs, free_el);
 		ocfs2_free(&backup_buf);
 	}
 	ocfs2_free_path(left_path);
diff --git a/libocfs2/extent_tree.h b/libocfs2/extent_tree.h
index 5f3c688..ca96008 100644
--- a/libocfs2/extent_tree.h
+++ b/libocfs2/extent_tree.h
@@ -97,3 +97,7 @@ struct ocfs2_extent_tree_operations {
 void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
 				   ocfs2_filesys *fs,
 				   char *buf, uint64_t blkno);
+errcode_t ocfs2_tree_insert_extent(ocfs2_filesys *fs,
+				   struct ocfs2_extent_tree *et,
+				   uint32_t cpos, uint64_t c_blkno,
+				   uint32_t clusters, uint16_t flag);
-- 
1.5.5




More information about the Ocfs2-tools-devel mailing list