[Ocfs2-tools-devel] [RFC 4/4] dx_dirs v1: indexed dir for fsck.ocfs2

Coly Li coly.li at suse.de
Sun Dec 20 10:02:42 PST 2009


This patch includes the rested part to support indexed dirs for fsck.ocfs2.

Signed-off-by: Coly Li <coly.li at suse.de>
---
diff --git a/fsck.ocfs2/dirblocks.c b/fsck.ocfs2/dirblocks.c
index 1fd5560..c502eef 100644
--- a/fsck.ocfs2/dirblocks.c
+++ b/fsck.ocfs2/dirblocks.c
@@ -134,6 +134,79 @@ static int try_to_cache(ocfs2_filesys *fs, struct rb_node *node,
 	return cached_blocks;
 }

+uint64_t o2fsck_search_reidx_dir(struct rb_root *root, uint64_t dino)
+{
+	struct rb_node *node = root->rb_node;
+	o2fsck_dirblock_entry *dbe;
+
+	while (node) {
+		dbe = rb_entry(node, o2fsck_dirblock_entry, e_node);
+
+		if (dino < dbe->e_ino)
+			node = node->rb_left;
+		else if (dino > dbe->e_ino)
+			node = node->rb_right;
+		else
+			return dbe->e_ino;
+	}
+	return 0;
+}
+
+static errcode_t o2fsck_add_reidx_dir_ino(struct rb_root *root, uint64_t dino)
+{
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+	o2fsck_dirblock_entry *dp, *tmp_dp;
+	errcode_t ret = 0;
+
+	dp = calloc(1, sizeof (*dp));
+	if (dp == NULL) {
+		ret = OCFS2_ET_NO_MEMORY;
+		goto out;
+	}
+
+	dp->e_ino = dino;
+
+	while(*p)
+	{
+		parent = *p;
+		tmp_dp = rb_entry(parent, o2fsck_dirblock_entry, e_node);
+
+		if (dp->e_ino < tmp_dp->e_ino)
+			p = &(*p)->rb_left;
+		else if (dp->e_ino > tmp_dp->e_ino)
+			p = &(*p)->rb_right;
+		else {
+			ret = OCFS2_ET_INTERNAL_FAILURE;
+			free(dp);
+			goto out;
+		}
+	}
+
+	rb_link_node(&dp->e_node, parent, p);
+	rb_insert_color(&dp->e_node, root);
+
+out:
+	return ret;
+}
+
+errcode_t o2fsck_try_add_reidx_dir(struct rb_root *root, uint64_t dino)
+{
+	errcode_t ret = 1;
+	uint64_t ino;
+	ino = o2fsck_search_reidx_dir(root, dino);
+	if (ino) {
+		ret = 0;
+		goto out;
+	}
+	ret = o2fsck_add_reidx_dir_ino(root, dino);
+	if (ret)
+		printf("some error happens.\n");
+
+out:
+	return ret;
+}
+
 void o2fsck_dir_block_iterate(o2fsck_state *ost, dirblock_iterator func,
 			      void *priv_data)
 {
@@ -174,3 +247,63 @@ void o2fsck_dir_block_iterate(o2fsck_state *ost, dirblock_iterator func,
 	if (pre_cache_buf)
 		ocfs2_free(&pre_cache_buf);
 }
+
+static int ocfs2_rebuild_indexed_dir(ocfs2_filesys *fs, uint64_t ino)
+{
+	int ret = 0;
+	char *di_buf = NULL, *dx_root_buf = NULL;
+	struct ocfs2_dinode *di;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &di_buf);
+	if (ret)
+		goto out;
+	
+	ret = ocfs2_read_inode(fs, ino, di_buf);
+	if (ret)
+		goto out;
+	di = (struct ocfs2_dinode *)di_buf;
+
+	ret = ocfs2_dx_dir_truncate(fs, di);
+	if (ret)
+		goto out;
+
+
+	/* do not rebuild indexed tree for inline directory */
+	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
+		printf("inode with OCFS2_INLINE_DATA_FL, do nothing.\n");
+		goto out;
+	}
+
+	if (di->i_dyn_features & OCFS2_INDEXED_DIR_FL) {
+//#		build new indexed-tree
+		goto out;
+	}
+
+out:
+	if (di_buf)
+		ocfs2_free(&di_buf);
+	if (dx_root_buf)
+		ocfs2_free(&dx_root_buf);
+	return ret;
+}
+
+
+void o2fsck_rebuild_indexed_dirs(ocfs2_filesys *fs, struct rb_root *root)
+{
+	struct rb_node *node;
+	o2fsck_dirblock_entry *dbe;
+	uint64_t ino;
+	int ret;
+
+	for (node = rb_first(root); node; node = rb_next(node)) {
+		dbe = rb_entry(node, o2fsck_dirblock_entry, e_node);
+		ino = dbe->e_ino;
+		ret = ocfs2_rebuild_indexed_dir(fs, ino);
+		if (ret)
+			printf("o2fsck_rebuilt_indexed_dir failed on %lu\n", ino);
+	}
+
+	ocfs2_flush_truncate_log_all(fs);
+}
+
+
diff --git a/fsck.ocfs2/include/dirblocks.h b/fsck.ocfs2/include/dirblocks.h
index 7b3a2e9..2940b6d 100644
--- a/fsck.ocfs2/include/dirblocks.h
+++ b/fsck.ocfs2/include/dirblocks.h
@@ -48,6 +48,9 @@ struct _o2fsck_state;
 void o2fsck_dir_block_iterate(struct _o2fsck_state *ost, dirblock_iterator func,
                               void *priv_data);
 		
+uint64_t o2fsck_search_reidx_dir(struct rb_root *root, uint64_t dino);
+errcode_t o2fsck_try_add_reidx_dir(struct rb_root *root, uint64_t dino);
+void o2fsck_rebuild_indexed_dirs(ocfs2_filesys *fs, struct rb_root *root);

 #endif /* __O2FSCK_DIRBLOCKS_H__ */

diff --git a/fsck.ocfs2/pass2.c b/fsck.ocfs2/pass2.c
index d61c501..c98feab 100644
--- a/fsck.ocfs2/pass2.c
+++ b/fsck.ocfs2/pass2.c
@@ -36,6 +36,7 @@
 #include <time.h>

 #include "ocfs2/ocfs2.h"
+#include "ocfs2/kernel-rbtree.h"

 #include "dirparents.h"
 #include "icount.h"
@@ -70,6 +71,7 @@ struct dirblock_data {
 	errcode_t	ret;
 	o2fsck_strings	strings;
 	uint64_t	last_ino;
+	struct rb_root	re_idx_dirs;
 };

 static int dirent_has_dots(struct ocfs2_dir_entry *dirent, int num_dots)
@@ -851,6 +853,14 @@ next:
 			com_err(whoami, ret, "while writing dir block %"PRIu64,
 				dbe->e_blkno);
 			dd->ost->ost_write_error = 1;
+			goto out;
+		}
+
+		if (ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super)) &&
+		    !(di->i_dyn_features & OCFS2_INLINE_DATA_FL)) {
+			ret = o2fsck_try_add_reidx_dir(&dd->re_idx_dirs, dbe->e_ino);
+			if (ret)
+				printf("there is something wrong\n");
 		}
 	}

@@ -860,6 +870,18 @@ out:
 	return ret_flags;
 }

+static void release_re_idx_dirs_rbtree(struct rb_root * root)
+{
+	struct rb_node *node;
+	o2fsck_dirblock_entry *dp;
+
+	while ((node = rb_first(root)) != NULL) {
+		dp = rb_entry(node, o2fsck_dirblock_entry, e_node);
+		rb_erase(&dp->e_node, root);
+		free(dp);
+	}
+}
+
 errcode_t o2fsck_pass2(o2fsck_state *ost)
 {
 	o2fsck_dir_parent *dp;
@@ -868,6 +890,7 @@ errcode_t o2fsck_pass2(o2fsck_state *ost)
 		.ost = ost,
 		.fs = ost->ost_fs,
 		.last_ino = 0,
+		.re_idx_dirs = RB_ROOT,
 	};

 	printf("Pass 2: Checking directory entries.\n");
@@ -905,6 +928,11 @@ errcode_t o2fsck_pass2(o2fsck_state *ost)
 		dp->dp_dirent = ost->ost_fs->fs_sysdir_blkno;

 	o2fsck_dir_block_iterate(ost, pass2_dir_block_iterate, &dd);
+
+	if (dd.re_idx_dirs.rb_node)
+		o2fsck_rebuild_indexed_dirs(ost->ost_fs, &dd.re_idx_dirs);
+	release_re_idx_dirs_rbtree(&dd.re_idx_dirs);
+
 	o2fsck_strings_free(&dd.strings);
 out:
 	if (dd.dirblock_buf)
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 8d677f0..b1039e9 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -405,7 +405,8 @@ errcode_t ocfs2_read_dx_root(ocfs2_filesys *fs, uint64_t block,
 errcode_t ocfs2_read_dx_leaf(ocfs2_filesys *fs, uint64_t block,
 			     void *buf);
 int ocfs2_dir_indexed(struct ocfs2_dinode *di);
-
+int ocfs2_dx_dir_truncate(ocfs2_filesys *fs, struct ocfs2_dinode *di);
+int ocfs2_flush_truncate_log_all(ocfs2_filesys *fs);
 errcode_t ocfs2_dir_iterate2(ocfs2_filesys *fs,
 			     uint64_t dir,
 			     int flags,
@@ -1256,6 +1257,10 @@ static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super_block *osb)
 #define OCFS2_BLOCK_ABORT	0x02
 #define OCFS2_BLOCK_ERROR	0x04

+
+#define OCFS2_IS_VALID_DX_ROOT(ptr)					\
+		(!strcmp((char *)(ptr)->dr_signature, OCFS2_DX_ROOT_SIGNATURE))
+
 /*
  * Block iterate flags
  *
diff --git a/libocfs2/Makefile b/libocfs2/Makefile
index 8e94cc3..6f210be 100644
--- a/libocfs2/Makefile
+++ b/libocfs2/Makefile
@@ -76,7 +76,9 @@ CFILES = 		\
 	quota.c		\
 	image.c		\
 	xattr.c		\
-	extent_tree.c
+	extent_tree.c	\
+	dealloc.c	\
+	dir_indexed.c

 HFILES =		\
 	bitmap.h	\

diff --git a/libocfs2/dirblock.c b/libocfs2/dirblock.c
index 06a1b64..62e48af 100644
--- a/libocfs2/dirblock.c
+++ b/libocfs2/dirblock.c
@@ -32,7 +32,7 @@

 #include "ocfs2/byteorder.h"
 #include "ocfs2/ocfs2.h"
-
+#include "dir_indexed.h"

 unsigned int ocfs2_dir_trailer_blk_off(ocfs2_filesys *fs)
 {

-- 
Coly Li
SuSE Labs



More information about the Ocfs2-tools-devel mailing list