[Ocfs2-tools-devel] [PATCH 08/10] libocfs2: Abstract extent split process.

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


ocfs2_mark_extent_written actually does the following things:
1. check the parameters.
2. Duplicate the extent block.
2. initialize the left_path and split_rec.
3. call __ocfs2_mark_extent_written. it will do:
   1) check the flags of unwritten
   2) do the real split work.
The whole process is packed tightly somehow. So this patch
will abstract 2 different functions so that future b-tree
operation can work with it.

1. __ocfs2_split_extent will accept path and split_rec and do
   the real split work.
2. ocfs2_change_extent_flag will accept a new flag and initialize
   path and split_rec.

So now ocfs2_mark_extent_written will do:
1. check the parameters.
2. Duplicate the extent block.
3. call ocfs2_change_extent_flag.
   1) initalize the left_path and split_rec.
   2) check whether the new flags conflict with the old one.
   3) call __ocfs2_split_extent to do the split.

The corresponding kernel commit is
555936bfcb1af26c6919d6cedb83710bb03d4322.

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 libocfs2/extend_file.c |   22 ++++++++++++
 libocfs2/extent_tree.c |   90 ++++++++++++++++++++++++-----------------------
 libocfs2/extent_tree.h |    5 +++
 3 files changed, 73 insertions(+), 44 deletions(-)

diff --git a/libocfs2/extend_file.c b/libocfs2/extend_file.c
index 8d157bc..fbb770a 100644
--- a/libocfs2/extend_file.c
+++ b/libocfs2/extend_file.c
@@ -248,6 +248,28 @@ out:
 	return ret;
 }
 
+/*
+ * Mark the already-existing extent at cpos as written for len clusters.
+ *
+ * If the existing extent is larger than the request, initiate a
+ * split. An attempt will be made at merging with adjacent extents.
+ *
+ */
+int ocfs2_mark_extent_written(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+			      uint32_t cpos, uint32_t len,
+			      uint64_t p_blkno)
+{
+	struct ocfs2_extent_tree et;
+
+	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);
+
+	return ocfs2_change_extent_flag(fs, &et, cpos, len, p_blkno,
+					0, OCFS2_EXT_UNWRITTEN);
+}
+
 #ifdef DEBUG_EXE
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/libocfs2/extent_tree.c b/libocfs2/extent_tree.c
index 2787f9a..c129dc3 100644
--- a/libocfs2/extent_tree.c
+++ b/libocfs2/extent_tree.c
@@ -293,14 +293,6 @@ static struct ocfs2_path *ocfs2_new_path(char *buf,
 	return path;
 }
 
-/*
- * Allocate and initialize a new path based on a disk inode tree.
- */
-static struct ocfs2_path *ocfs2_new_inode_path(struct ocfs2_dinode *di)
-{
-	return ocfs2_new_path((char *)di, &di->id2.i_list, di->i_blkno);
-}
-
 static struct ocfs2_path *ocfs2_new_path_from_path(struct ocfs2_path *path)
 {
 	return ocfs2_new_path(path_root_buf(path), path_root_el(path),
@@ -3587,9 +3579,8 @@ out:
 }
 
 /*
- * Mark part or all of the extent record at split_index in the leaf
- * pointed to by path as written. This removes the unwritten
- * extent flag.
+ * Split part or all of the extent record at split_index in the leaf
+ * pointed to by path. Merge with the contiguous extent record if needed.
  *
  * Care is taken to handle contiguousness so as to not grow the tree.
  *
@@ -3600,9 +3591,9 @@ out:
  * This code is optimized for readability - several passes might be
  * made over certain portions of the tree.
  */
-static int __ocfs2_mark_extent_written(struct insert_ctxt *insert_ctxt,
-				       struct ocfs2_path *path,
-				       int split_index)
+static int ocfs2_split_extent(struct insert_ctxt *insert_ctxt,
+			      struct ocfs2_path *path,
+			      int split_index)
 {
 	int ret = 0;
 	struct ocfs2_extent_rec split_rec = insert_ctxt->rec;
@@ -3613,11 +3604,6 @@ static int __ocfs2_mark_extent_written(struct insert_ctxt *insert_ctxt,
 	struct ocfs2_extent_list *rightmost_el;
 	ocfs2_filesys *fs = insert_ctxt->fs;
 
-	if (!rec->e_flags & OCFS2_EXT_UNWRITTEN) {
-		ret = OCFS2_ET_INVALID_ARGUMENT;
-		goto out;
-	}
-
 	if (rec->e_cpos > split_rec.e_cpos ||
 	    ((rec->e_cpos + rec->e_leaf_clusters) <
 	     (split_rec.e_cpos + split_rec.e_leaf_clusters))) {
@@ -3684,27 +3670,27 @@ out:
 }
 
 /*
- * Mark the already-existing extent at cpos as written for len clusters.
+ * Change the flags of the already-existing extent at cpos for len clusters.
+ *
+ * new_flags: the flags we want to set.
+ * clear_flags: the flags we want to clear.
+ * p_blkno: the new physical offset we want this new extent starts from.
  *
  * If the existing extent is larger than the request, initiate a
  * split. An attempt will be made at merging with adjacent extents.
- *
  */
-int ocfs2_mark_extent_written(ocfs2_filesys *fs, struct ocfs2_dinode *di,
-			      uint32_t cpos, uint32_t len,
-			      uint64_t p_blkno)
+int ocfs2_change_extent_flag(ocfs2_filesys *fs,
+			     struct ocfs2_extent_tree *et,
+			     uint32_t cpos, uint32_t len,
+			     uint64_t p_blkno,
+			     int new_flags, int clear_flags)
 {
 	int ret, index;
 	struct ocfs2_path *left_path = NULL;
 	struct ocfs2_extent_list *el;
 	struct insert_ctxt ctxt;
-	struct ocfs2_extent_tree et;
-	char *backup_buf = NULL, *di_buf = NULL;
-
-	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);
+	struct ocfs2_extent_rec *rec;
+	char *backup_buf = NULL;
 
 	/* In order to orderize the written block sequence and avoid
 	 * the corruption for the inode, we duplicate the extent block
@@ -3714,27 +3700,26 @@ int ocfs2_mark_extent_written(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 	 * And if the duplicate process fails, we should go on the normal
 	 * insert process.
 	 */
-	di_buf = (char *)di;
-	if (di->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 out;
 
-		memcpy(backup_buf, di_buf, fs->fs_blocksize);
+		memcpy(backup_buf, et->et_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_et(fs, &et);
+		ret = duplicate_extent_block_et(fs, et);
 		if (ret) {
-			memcpy(di_buf, backup_buf,fs->fs_blocksize);
+			memcpy(et->et_root_buf, backup_buf, fs->fs_blocksize);
 			ocfs2_free(&backup_buf);
 			backup_buf = NULL;
 		}
 	}
 
-	left_path = ocfs2_new_inode_path(di);
+	left_path = ocfs2_new_path_from_et(et);
 	if (!left_path) {
 		ret = OCFS2_ET_NO_MEMORY;
 		goto out;
@@ -3753,25 +3738,42 @@ int ocfs2_mark_extent_written(ocfs2_filesys *fs, struct ocfs2_dinode *di,
 	}
 
 	ctxt.fs = fs;
-	ctxt.et = &et;
+	ctxt.et = et;
+
+	ret = OCFS2_ET_IO;
+	rec = &el->l_recs[index];
+	if (new_flags && (rec->e_flags & new_flags))
+		goto out;
+
+	if (clear_flags && !(rec->e_flags & clear_flags))
+		goto out;
 
 	memset(&ctxt.rec, 0, sizeof(struct ocfs2_extent_rec));
 	ctxt.rec.e_cpos = cpos;
 	ctxt.rec.e_leaf_clusters = len;
 	ctxt.rec.e_blkno = p_blkno;
-	ctxt.rec.e_flags = path_leaf_el(left_path)->l_recs[index].e_flags;
-	ctxt.rec.e_flags &= ~OCFS2_EXT_UNWRITTEN;
+	ctxt.rec.e_flags = rec->e_flags;
+	if (new_flags)
+		ctxt.rec.e_flags |= new_flags;
+	if (clear_flags)
+		ctxt.rec.e_flags &= ~clear_flags;
 
-	ret = __ocfs2_mark_extent_written(&ctxt, left_path, index);
+	ret = ocfs2_split_extent(&ctxt, left_path, index);
 	if (ret)
 		goto out;
 
-	ret = ocfs2_write_inode(fs, di->i_blkno, di_buf);
+	/*
+	 * 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, et->et_root_buf);
 
 out:
 	if (backup_buf) {
 		struct ocfs2_extent_list *free_el;
-		int offset = (char *)et.et_root_el - et.et_root_buf;
+		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.
@@ -3779,7 +3781,7 @@ out:
 
 		if (ret)
 			free_el = (struct ocfs2_extent_list *)
-						(di_buf + offset);
+					(et->et_root_buf + offset);
 		else
 			free_el = (struct ocfs2_extent_list *)
 						(backup_buf + offset);
diff --git a/libocfs2/extent_tree.h b/libocfs2/extent_tree.h
index ca96008..97a911c 100644
--- a/libocfs2/extent_tree.h
+++ b/libocfs2/extent_tree.h
@@ -101,3 +101,8 @@ 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);
+int ocfs2_change_extent_flag(ocfs2_filesys *fs,
+			     struct ocfs2_extent_tree *et,
+			     uint32_t cpos, uint32_t len,
+			     uint64_t p_blkno,
+			     int new_flags, int clear_flags);
-- 
1.5.5




More information about the Ocfs2-tools-devel mailing list