[Ocfs2-tools-devel] [PATCH 37/44] fsck.ocfs2: Store refcounted clusters.
Tao Ma
tao.ma at ORACLE.COM
Mon Dec 28 01:01:22 PST 2009
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 826b9f8..25ff134 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 a35164b..0bb7666 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 {
@@ -246,6 +256,11 @@ static errcode_t check_rb(o2fsck_state *ost, uint64_t blkno,
ei.para = ✓
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;
@@ -364,3 +379,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