[Ocfs2-tools-devel] [PATCH 37/50] fsck.ocfs2: Store refcounted clusters.

Tao Ma tao.ma at oracle.com
Mon Jan 11 07:31:23 PST 2010


In case we see a refcounted clusters, we don't add
them to stored bitmaps. Instead, we store it to
a rb-tree so that we can check them later.

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 fsck.ocfs2/extent.c           |   29 +++++++++++++--
 fsck.ocfs2/include/extent.h   |    9 +++++
 fsck.ocfs2/include/fsck.h     |    3 ++
 fsck.ocfs2/include/refcount.h |    6 +++
 fsck.ocfs2/refcount.c         |   79 +++++++++++++++++++++++++++++++++++++++++
 fsck.ocfs2/xattr.c            |    2 +
 6 files changed, 125 insertions(+), 3 deletions(-)

diff --git a/fsck.ocfs2/extent.c b/fsck.ocfs2/extent.c
index bd1ccff..0075319 100644
--- a/fsck.ocfs2/extent.c
+++ b/fsck.ocfs2/extent.c
@@ -43,6 +43,7 @@
 #include "fsck.h"
 #include "problem.h"
 #include "util.h"
+#include "refcount.h"
 
 static const char *whoami = "extent.c";
 
@@ -293,9 +294,8 @@ errcode_t check_el(o2fsck_state *ost, struct extent_info *ei,
 			continue;
 
 		/* mark the data clusters as used */
-		o2fsck_mark_clusters_allocated(ost,
-			ocfs2_blocks_to_clusters(ost->ost_fs, er->e_blkno),
-			clusters);
+		if (ei->mark_rec_alloc_func)
+			ei->mark_rec_alloc_func(ost, er, clusters, ei->para);
 
 		ei->ei_clusters += clusters;
 
@@ -383,6 +383,28 @@ errcode_t o2fsck_check_extent_rec(o2fsck_state *ost,
 	return 0;
 }
 
+errcode_t o2fsck_mark_tree_clusters_allocated(o2fsck_state *ost,
+					      struct ocfs2_extent_rec *rec,
+					      uint32_t clusters,
+					      void *para)
+{
+	struct ocfs2_dinode *di = para;
+	errcode_t ret = 0;
+
+	if (rec->e_flags & OCFS2_EXT_REFCOUNTED)
+		ret = o2fsck_mark_clusters_refcounted(ost,
+						      di->i_refcount_loc,
+						      di->i_blkno,
+			ocfs2_blocks_to_clusters(ost->ost_fs, rec->e_blkno),
+			clusters, rec->e_cpos);
+	else
+		o2fsck_mark_clusters_allocated(ost,
+			ocfs2_blocks_to_clusters(ost->ost_fs, rec->e_blkno),
+			clusters);
+
+	return ret;
+}
+
 errcode_t o2fsck_check_extents(o2fsck_state *ost,
 			       struct ocfs2_dinode *di)
 {
@@ -391,6 +413,7 @@ errcode_t o2fsck_check_extents(o2fsck_state *ost,
 	int changed = 0;
 
 	ei.chk_rec_func = o2fsck_check_extent_rec;
+	ei.mark_rec_alloc_func = o2fsck_mark_tree_clusters_allocated;
 	ei.para = di;
 	ret = check_el(ost, &ei, di->i_blkno, &di->id2.i_list,
 	         ocfs2_extent_recs_per_inode(ost->ost_fs->fs_blocksize),
diff --git a/fsck.ocfs2/include/extent.h b/fsck.ocfs2/include/extent.h
index 857d7fd..fe9b021 100644
--- a/fsck.ocfs2/include/extent.h
+++ b/fsck.ocfs2/include/extent.h
@@ -28,6 +28,10 @@ typedef errcode_t (check_leaf_er_func)(o2fsck_state *ost,
 				       struct ocfs2_extent_rec *er,
 				       int *changed,
 				       void *para);
+typedef errcode_t (mark_leaf_er_alloc_func)(o2fsck_state *ost,
+					    struct ocfs2_extent_rec *er,
+					    uint32_t clusters,
+					    void *para);
 
 struct extent_info {
 	uint64_t		ei_max_size;
@@ -36,6 +40,7 @@ struct extent_info {
 	uint16_t		ei_expected_depth;
 	unsigned		ei_expect_depth:1;
 	check_leaf_er_func	*chk_rec_func;
+	mark_leaf_er_alloc_func	*mark_rec_alloc_func;
 	void			*para;
 };
 
@@ -53,5 +58,9 @@ errcode_t o2fsck_check_extent_rec(o2fsck_state *ost,
 				  int *changed,
 				  void *para);
 
+errcode_t o2fsck_mark_tree_clusters_allocated(o2fsck_state *ost,
+					      struct ocfs2_extent_rec *rec,
+					      uint32_t clusters,
+					      void *para);
 #endif /* __O2FSCK_EXTENT_H__ */
 
diff --git a/fsck.ocfs2/include/fsck.h b/fsck.ocfs2/include/fsck.h
index f671a8a..2ca295a 100644
--- a/fsck.ocfs2/include/fsck.h
+++ b/fsck.ocfs2/include/fsck.h
@@ -29,6 +29,8 @@
 #include "icount.h"
 #include "dirblocks.h"
 
+struct refcount_file;
+
 typedef struct _o2fsck_state {
 	ocfs2_filesys 	*ost_fs;
 
@@ -59,6 +61,7 @@ typedef struct _o2fsck_state {
 	struct rb_root	ost_dir_parents;
 
 	struct rb_root	ost_refcount_trees;
+	struct refcount_file *ost_latest_file;
 
 	unsigned	ost_ask:1,	/* confirm with the user */
 			ost_answer:1,	/* answer if we don't ask the user */
diff --git a/fsck.ocfs2/include/refcount.h b/fsck.ocfs2/include/refcount.h
index ed59b16..4e4f901 100644
--- a/fsck.ocfs2/include/refcount.h
+++ b/fsck.ocfs2/include/refcount.h
@@ -22,5 +22,11 @@
 
 errcode_t o2fsck_check_refcount_tree(o2fsck_state *ost,
 				     struct ocfs2_dinode *di);
+errcode_t o2fsck_mark_clusters_refcounted(o2fsck_state *ost,
+					  uint64_t rf_blkno,
+					  uint64_t i_blkno,
+					  uint64_t p_cpos,
+					  uint32_t clusters,
+					  uint32_t v_cpos);
 #endif /* __O2FSCK_REFCOUNT_H__ */
 
diff --git a/fsck.ocfs2/refcount.c b/fsck.ocfs2/refcount.c
index 346117d..62dfdce 100644
--- a/fsck.ocfs2/refcount.c
+++ b/fsck.ocfs2/refcount.c
@@ -35,9 +35,19 @@ struct check_refcount_rec {
 	uint64_t c_end;
 };
 
+/* every REFCOUNTED ocfs2_extent_rec will become one. */
+struct refcount_extent {
+	struct rb_node ext_node;
+	uint32_t v_cpos;
+	uint32_t clusters;
+	uint64_t p_cpos;
+};
+
 struct refcount_file {
 	struct list_head list;
 	uint64_t i_blkno;
+	struct rb_root ref_extents; /* store every refcounted extent rec
+				     * in this file. */
 };
 
 struct refcount_tree {
@@ -257,6 +267,11 @@ static errcode_t check_rb(o2fsck_state *ost, uint64_t blkno,
 
 		ei.para = &check;
 		ei.chk_rec_func = refcount_check_leaf_extent_rec;
+		/*
+		 * leaf extent rec for a refcount tree is allocated from
+		 * extent_alloc, so we don't need to set mark_rec_alloc_func
+		 * here.
+		 */
 		check_el(ost, &ei, rb->rf_blkno, &rb->rf_list,
 			 max_recs, &changed);
 		*c_end = check.c_end;
@@ -395,3 +410,67 @@ check_valid:
 
 	return ret;
 }
+
+static void refcount_extent_insert(struct refcount_file *file,
+				   struct refcount_extent *insert)
+{
+	struct rb_node **p = &file->ref_extents.rb_node;
+	struct rb_node *parent = NULL;
+	struct refcount_extent *extent = NULL;
+
+	while (*p) {
+		parent = *p;
+		extent = rb_entry(parent, struct refcount_extent, ext_node);
+		if (insert->p_cpos < extent->p_cpos)
+			p = &(*p)->rb_left;
+		else if (insert->p_cpos > extent->p_cpos)
+			p = &(*p)->rb_right;
+		else
+			assert(0);  /* Caller checked */
+	}
+
+	rb_link_node(&insert->ext_node, parent, p);
+	rb_insert_color(&insert->ext_node, &file->ref_extents);
+}
+
+errcode_t o2fsck_mark_clusters_refcounted(o2fsck_state *ost,
+					  uint64_t rf_blkno,
+					  uint64_t i_blkno,
+					  uint64_t p_cpos,
+					  uint32_t clusters,
+					  uint32_t v_cpos)
+{
+	errcode_t ret;
+	struct refcount_tree *tree;
+	struct refcount_file *file = ost->ost_latest_file;
+	struct list_head *p, *next;
+	struct refcount_extent *extent;
+
+	if (file && file->i_blkno == i_blkno)
+		goto add_clusters;
+
+	tree = refcount_tree_lookup(ost, rf_blkno);
+	/* We should already insert the tree during refcount tree check. */
+	assert(tree);
+
+	list_for_each_safe(p, next, &tree->files_list) {
+		file = list_entry(p, struct refcount_file, list);
+		if (file->i_blkno == i_blkno)
+			goto add_clusters;
+	}
+	/* We should already insert the file during refcount tree check. */
+	assert(0);
+
+add_clusters:
+	ost->ost_latest_file = file;
+	ret = ocfs2_malloc0(sizeof(struct refcount_extent), &extent);
+	if (ret)
+		return ret;
+
+	extent->v_cpos = v_cpos;
+	extent->clusters = clusters;
+	extent->p_cpos = p_cpos;
+
+	refcount_extent_insert(file, extent);
+	return 0;
+}
diff --git a/fsck.ocfs2/xattr.c b/fsck.ocfs2/xattr.c
index 07cc97d..46c54d4 100644
--- a/fsck.ocfs2/xattr.c
+++ b/fsck.ocfs2/xattr.c
@@ -381,6 +381,7 @@ static errcode_t check_xattr_value(o2fsck_state *ost,
 	uint64_t owner;
 
 	ei.chk_rec_func = o2fsck_check_extent_rec;
+	ei.mark_rec_alloc_func = o2fsck_mark_tree_clusters_allocated;
 	ei.para = di;
 	for (i = 0 ; i < xh->xh_count; i++) {
 		int change = 0;
@@ -608,6 +609,7 @@ static errcode_t o2fsck_check_xattr_index_block(o2fsck_state *ost,
 		return 0;
 
 	ei.chk_rec_func = o2fsck_check_extent_rec;
+	ei.mark_rec_alloc_func = o2fsck_mark_tree_clusters_allocated;
 	ei.para = di;
 	ret = check_el(ost, &ei, xb->xb_blkno, el,
 		ocfs2_xattr_recs_per_xb(ost->ost_fs->fs_blocksize),
-- 
1.5.5




More information about the Ocfs2-tools-devel mailing list