[Ocfs2-devel] [PATCH 08/42] ocfs2: Wrap manipulation of leaf extent record in b-tree operation.

Tao Ma tao.ma at oracle.com
Thu Apr 2 16:45:47 PDT 2009


In b-tree operation, when we merge/split an already existing extent
record, we need to modify e_blkno, e_cpos and e_leaf_clusters. While
with the ocfs2_extent_rec in a refcount tree, some fields now have
different meanings. So wrap the modification of leaf extent record
so that we can make it usable for the refcount tree.

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 fs/ocfs2/alloc.c |  140 ++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 89 insertions(+), 51 deletions(-)

diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index e1ddf9b..e88c949 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -60,6 +60,11 @@ enum ocfs2_contig_type {
 	CONTIG_LEFTRIGHT,
 };
 
+enum ocfs2_leaf_rec_change_type {
+	LEAF_CHANGE_LEFT = 0,
+	LEAF_CHANGE_RIGHT,
+};
+
 static enum ocfs2_contig_type
 	ocfs2_extent_rec_contig(struct super_block *sb,
 				struct ocfs2_extent_rec *ext,
@@ -143,6 +148,18 @@ struct ocfs2_extent_tree_operations {
 		(*eo_ocfs2_extent_contig)(struct super_block *sb,
 					  struct ocfs2_extent_rec *ext,
 					  struct ocfs2_extent_rec *insert_rec);
+
+	/*
+	 * Change the specified leaf extent record.
+	 * type indicates the action we need to do with the rec.
+	 * If clusters < 0, it means shrinking instead of extension.
+	 * Optional. Don't need to set it if use ocfs2_extent_rec as the
+	 * tree leaf.
+	 */
+	void (*eo_leaf_rec_change)(struct super_block *sb,
+				   struct ocfs2_extent_rec *rec,
+				   enum ocfs2_leaf_rec_change_type type,
+				   int clusters);
 };
 
 
@@ -339,6 +356,24 @@ static struct ocfs2_extent_tree_operations ocfs2_xattr_tree_et_ops = {
 	.eo_fill_max_leaf_clusters = ocfs2_xattr_tree_fill_max_leaf_clusters,
 };
 
+static void ocfs2_leaf_extent_rec_change(struct super_block *sb,
+					 struct ocfs2_extent_rec *rec,
+					 enum ocfs2_leaf_rec_change_type type,
+					 int clusters)
+{
+	if (type == LEAF_CHANGE_LEFT) {
+		le32_add_cpu(&rec->e_cpos, -clusters);
+		if (clusters > 0)
+			le64_add_cpu(&rec->e_blkno,
+			     -ocfs2_clusters_to_blocks(sb, clusters));
+		else
+			le64_add_cpu(&rec->e_blkno,
+			     ocfs2_clusters_to_blocks(sb, -clusters));
+	}
+
+	le16_add_cpu(&rec->e_leaf_clusters, clusters);
+}
+
 static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *et,
 				     struct ocfs2_caching_info *ci,
 				     struct buffer_head *bh,
@@ -362,6 +397,9 @@ static void __ocfs2_init_extent_tree(struct ocfs2_extent_tree *et,
 
 	if (!et->et_ops->eo_ocfs2_extent_contig)
 		et->et_ops->eo_ocfs2_extent_contig = ocfs2_extent_rec_contig;
+
+	if (!et->et_ops->eo_leaf_rec_change)
+		et->et_ops->eo_leaf_rec_change = ocfs2_leaf_extent_rec_change;
 }
 
 void ocfs2_init_dinode_extent_tree(struct ocfs2_extent_tree *et,
@@ -437,6 +475,16 @@ static inline enum ocfs2_contig_type
 			ext, insert_rec);
 }
 
+static inline void ocfs2_et_leaf_rec_change(struct ocfs2_extent_tree *et,
+					struct ocfs2_extent_rec *rec,
+					enum ocfs2_leaf_rec_change_type type,
+					int clusters)
+{
+	return et->et_ops->eo_leaf_rec_change(
+				ocfs2_metadata_cache_get_super(et->et_ci),
+				rec, type, clusters);
+}
+
 static inline int ocfs2_et_insert_check(struct ocfs2_extent_tree *et,
 					struct ocfs2_extent_rec *rec)
 {
@@ -3302,13 +3350,11 @@ static int ocfs2_merge_rec_right(struct ocfs2_path *left_path,
 		goto out;
 	}
 
-	le16_add_cpu(&left_rec->e_leaf_clusters, -split_clusters);
+	ocfs2_et_leaf_rec_change(et, left_rec,
+				 LEAF_CHANGE_RIGHT, -split_clusters);
 
-	le32_add_cpu(&right_rec->e_cpos, -split_clusters);
-	le64_add_cpu(&right_rec->e_blkno,
-		     -ocfs2_clusters_to_blocks(ocfs2_metadata_cache_get_super(et->et_ci),
-					       split_clusters));
-	le16_add_cpu(&right_rec->e_leaf_clusters, split_clusters);
+	ocfs2_et_leaf_rec_change(et, right_rec,
+				 LEAF_CHANGE_LEFT, split_clusters);
 
 	ocfs2_cleanup_merge(el, index);
 
@@ -3479,13 +3525,11 @@ static int ocfs2_merge_rec_left(struct ocfs2_path *right_path,
 
 		has_empty_extent = 0;
 	} else
-		le16_add_cpu(&left_rec->e_leaf_clusters, split_clusters);
+		ocfs2_et_leaf_rec_change(et, left_rec,
+					 LEAF_CHANGE_RIGHT, split_clusters);
 
-	le32_add_cpu(&right_rec->e_cpos, split_clusters);
-	le64_add_cpu(&right_rec->e_blkno,
-		     ocfs2_clusters_to_blocks(ocfs2_metadata_cache_get_super(et->et_ci),
-					      split_clusters));
-	le16_add_cpu(&right_rec->e_leaf_clusters, -split_clusters);
+	ocfs2_et_leaf_rec_change(et, right_rec,
+				 LEAF_CHANGE_LEFT, -split_clusters);
 
 	ocfs2_cleanup_merge(el, index);
 
@@ -3664,33 +3708,27 @@ out:
 	return ret;
 }
 
-static void ocfs2_subtract_from_rec(struct super_block *sb,
+static void ocfs2_subtract_from_rec(struct ocfs2_extent_tree *et,
 				    enum ocfs2_split_type split,
 				    struct ocfs2_extent_rec *rec,
 				    struct ocfs2_extent_rec *split_rec)
 {
-	u64 len_blocks;
-
-	len_blocks = ocfs2_clusters_to_blocks(sb,
-				le16_to_cpu(split_rec->e_leaf_clusters));
+	int clusters = le16_to_cpu(split_rec->e_leaf_clusters);
 
 	if (split == SPLIT_LEFT) {
 		/*
 		 * Region is on the left edge of the existing
 		 * record.
 		 */
-		le32_add_cpu(&rec->e_cpos,
-			     le16_to_cpu(split_rec->e_leaf_clusters));
-		le64_add_cpu(&rec->e_blkno, len_blocks);
-		le16_add_cpu(&rec->e_leaf_clusters,
-			     -le16_to_cpu(split_rec->e_leaf_clusters));
+		ocfs2_et_leaf_rec_change(et, rec,
+					 LEAF_CHANGE_LEFT, -clusters);
 	} else {
 		/*
 		 * Region is on the right edge of the existing
 		 * record.
 		 */
-		le16_add_cpu(&rec->e_leaf_clusters,
-			     -le16_to_cpu(split_rec->e_leaf_clusters));
+		ocfs2_et_leaf_rec_change(et, rec,
+					 LEAF_CHANGE_RIGHT, -clusters);
 	}
 }
 
@@ -3707,6 +3745,7 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_tree *et,
 	int i = insert->ins_contig_index;
 	unsigned int range;
 	struct ocfs2_extent_rec *rec;
+	unsigned int insert_clusters = le16_to_cpu(insert_rec->e_leaf_clusters);
 
 	BUG_ON(le16_to_cpu(el->l_tree_depth) != 0);
 
@@ -3714,7 +3753,7 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_tree *et,
 		i = ocfs2_search_extent_list(el, le32_to_cpu(insert_rec->e_cpos));
 		BUG_ON(i == -1);
 		rec = &el->l_recs[i];
-		ocfs2_subtract_from_rec(ocfs2_metadata_cache_get_super(et->et_ci),
+		ocfs2_subtract_from_rec(et,
 					insert->ins_split, rec,
 					insert_rec);
 		goto rotate;
@@ -3726,11 +3765,14 @@ static void ocfs2_insert_at_leaf(struct ocfs2_extent_tree *et,
 	if (insert->ins_contig != CONTIG_NONE) {
 		rec = &el->l_recs[i];
 		if (insert->ins_contig == CONTIG_LEFT) {
-			rec->e_blkno = insert_rec->e_blkno;
-			rec->e_cpos = insert_rec->e_cpos;
-		}
-		le16_add_cpu(&rec->e_leaf_clusters,
-			     le16_to_cpu(insert_rec->e_leaf_clusters));
+			ocfs2_et_leaf_rec_change(et, rec,
+						 LEAF_CHANGE_LEFT,
+						 insert_clusters);
+		} else
+			ocfs2_et_leaf_rec_change(et, rec,
+						 LEAF_CHANGE_RIGHT,
+						 insert_clusters);
+
 		return;
 	}
 
@@ -3985,8 +4027,7 @@ static void ocfs2_split_record(struct ocfs2_extent_tree *et,
 	}
 
 	rec = &el->l_recs[index];
-	ocfs2_subtract_from_rec(ocfs2_metadata_cache_get_super(et->et_ci),
-				split, rec, split_rec);
+	ocfs2_subtract_from_rec(et, split, rec, split_rec);
 	ocfs2_rotate_leaf(insert_el, split_rec);
 }
 
@@ -4724,24 +4765,23 @@ leave:
 	return status;
 }
 
-static void ocfs2_make_right_split_rec(struct super_block *sb,
+static void ocfs2_make_right_split_rec(struct ocfs2_extent_tree *et,
 				       struct ocfs2_extent_rec *split_rec,
 				       u32 cpos,
 				       struct ocfs2_extent_rec *rec)
 {
 	u32 rec_cpos = le32_to_cpu(rec->e_cpos);
-	u32 rec_range = rec_cpos + le16_to_cpu(rec->e_leaf_clusters);
-
-	memset(split_rec, 0, sizeof(struct ocfs2_extent_rec));
 
-	split_rec->e_cpos = cpu_to_le32(cpos);
-	split_rec->e_leaf_clusters = cpu_to_le16(rec_range - cpos);
-
-	split_rec->e_blkno = rec->e_blkno;
-	le64_add_cpu(&split_rec->e_blkno,
-		     ocfs2_clusters_to_blocks(sb, cpos - rec_cpos));
+	/*
+	 * We want to create a right split rec which start from cpos
+	 * while end at the original rec's end. So we first make
+	 * the split_rec the same as rec and then shrink it to the
+	 * specified size.
+	 */
+	*split_rec = *rec;
 
-	split_rec->e_flags = rec->e_flags;
+	ocfs2_et_leaf_rec_change(et, split_rec, LEAF_CHANGE_LEFT,
+				 rec_cpos - cpos);
 }
 
 static int ocfs2_split_and_insert(handle_t *handle,
@@ -4808,8 +4848,7 @@ leftright:
 		 */
 		insert.ins_split = SPLIT_RIGHT;
 
-		ocfs2_make_right_split_rec(ocfs2_metadata_cache_get_super(et->et_ci),
-					   &tmprec, insert_range, &rec);
+		ocfs2_make_right_split_rec(et, &tmprec, insert_range, &rec);
 
 		split_rec = tmprec;
 
@@ -5090,8 +5129,7 @@ static int ocfs2_split_tree(handle_t *handle, struct ocfs2_extent_tree *et,
 	 */
 	el = path_leaf_el(path);
 	rec = &el->l_recs[index];
-	ocfs2_make_right_split_rec(ocfs2_metadata_cache_get_super(et->et_ci),
-				   &split_rec, new_range, rec);
+	ocfs2_make_right_split_rec(et, &split_rec, new_range, rec);
 
 	depth = path->p_tree_depth;
 	if (depth > 0) {
@@ -5260,12 +5298,12 @@ static int ocfs2_truncate_rec(handle_t *handle,
 		}
 	} else if (le32_to_cpu(rec->e_cpos) == cpos) {
 		/* Remove leftmost portion of the record. */
-		le32_add_cpu(&rec->e_cpos, len);
-		le64_add_cpu(&rec->e_blkno, ocfs2_clusters_to_blocks(sb, len));
-		le16_add_cpu(&rec->e_leaf_clusters, -len);
+		ocfs2_et_leaf_rec_change(et, rec,
+					 LEAF_CHANGE_LEFT, -len);
 	} else if (rec_range == trunc_range) {
 		/* Remove rightmost portion of the record */
-		le16_add_cpu(&rec->e_leaf_clusters, -len);
+		ocfs2_et_leaf_rec_change(et, rec,
+					 LEAF_CHANGE_RIGHT, -len);
 		if (is_rightmost_tree_rec)
 			ocfs2_adjust_rightmost_records(handle, et, path, rec);
 	} else {
-- 
1.6.2.rc2.16.gf474c




More information about the Ocfs2-devel mailing list