[Ocfs2-tools-devel] [PATCH 08/15] dx_dirs v10: fsck.ocfs2 support

Mark Fasheh mfasheh at suse.com
Wed Mar 31 16:12:55 PDT 2010


On Thu, Mar 25, 2010 at 03:51:03AM +0800, Coly Li wrote:
> This patch does a basic indexed dirs support in fsck.ocfs2.
> 
> During pass2, if a directory block is changed, and indexed dirs in
> enabled, the indexed tree of this directory will be
> truncate, then rebuild with the modified directory data. All the
> modified directories' inode numbers are recored in a
> rb-tree, when all directories get scanned, truncate and rebuild the
> directories whose inode recorded in the rb-tree.
> 
> Signed-off-by: Coly Li <coly.li at suse.de>
> Cc: Mark Fasheh <mfasheh at suse.com>
> ---
>  fsck.ocfs2/dirblocks.c         |  127 ++++++++++++++++++++++++++++++++++++++--
>  fsck.ocfs2/include/dirblocks.h |    4 +
>  fsck.ocfs2/pass1.c             |   54 +++++++++++++++++
>  fsck.ocfs2/pass1b.c            |    4 +-
>  fsck.ocfs2/pass2.c             |   47 ++++++++++++++-
>  fsck.ocfs2/pass3.c             |    1 +
>  fsck.ocfs2/pass4.c             |    1 +
>  7 files changed, 229 insertions(+), 9 deletions(-)
> 
> diff --git a/fsck.ocfs2/dirblocks.c b/fsck.ocfs2/dirblocks.c
> index 1fd5560..b3519d7 100644
> --- a/fsck.ocfs2/dirblocks.c
> +++ b/fsck.ocfs2/dirblocks.c
> @@ -34,6 +34,7 @@
>  #include "fsck.h"
>  #include "dirblocks.h"
>  #include "util.h"
> +#include "extent.h"
> 
>  errcode_t o2fsck_add_dir_block(o2fsck_dirblocks *db, uint64_t ino,
>  			       uint64_t blkno, uint64_t blkcount)
> @@ -43,11 +44,9 @@ errcode_t o2fsck_add_dir_block(o2fsck_dirblocks *db, uint64_t ino,
>  	o2fsck_dirblock_entry *dbe, *tmp_dbe;
>  	errcode_t ret = 0;
> 
> -	dbe = calloc(1, sizeof(*dbe));
> -	if (dbe == NULL) {
> -		ret = OCFS2_ET_NO_MEMORY;
> -		goto out;
> -	}
> +	ret = ocfs2_malloc0(sizeof(o2fsck_dirblock_entry), &dbe);
> +	if (ret)
> +       		goto out;
> 
>  	dbe->e_ino = ino;
>  	dbe->e_blkno = blkno;
> @@ -134,6 +133,73 @@ 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;
> +
> +	ret = ocfs2_malloc0(sizeof (o2fsck_dirblock_entry), &dp);
> +	if (ret)
> +		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;
> +			ocfs2_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 = 0;
> +	uint64_t ino;
> +	ino = o2fsck_search_reidx_dir(root, dino);
> +	if (ino)
> +		goto out;
> +	ret = o2fsck_add_reidx_dir_ino(root, dino);
> +
> +out:
> +	return ret;
> +}
> +
>  void o2fsck_dir_block_iterate(o2fsck_state *ost, dirblock_iterator func,
>  			      void *priv_data)
>  {
> @@ -174,3 +240,54 @@ void o2fsck_dir_block_iterate(o2fsck_state *ost, dirblock_iterator func,
>  	if (pre_cache_buf)
>  		ocfs2_free(&pre_cache_buf);
>  }
> +
> +static errcode_t ocfs2_rebuild_indexed_dir(ocfs2_filesys *fs, uint64_t ino)
> +{
> +	errcode_t ret = 0;
> +	char *di_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;
> +
> +	/* do not rebuild indexed tree for inline directory */
> +	if (di->i_dyn_features & OCFS2_INLINE_DATA_FL)
> +		goto out;
> +
> +	ret = ocfs2_dx_dir_truncate(fs, ino);
> +	if (ret)
> +		goto out;
> +
> +	ret = ocfs2_dx_dir_build(fs, ino);
> +out:
> +	if (di_buf)
> +		ocfs2_free(&di_buf);
> +	return ret;
> +}
> +
> +
> +errcode_t o2fsck_rebuild_indexed_dirs(ocfs2_filesys *fs, struct rb_root *root)
> +{
> +	struct rb_node *node;
> +	o2fsck_dirblock_entry *dbe;
> +	uint64_t ino;
> +	errcode_t ret = 0;
> +
> +	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)
> +			goto out;
> +	}
> +out:
> +	return ret;
> +}
> +
> diff --git a/fsck.ocfs2/include/dirblocks.h b/fsck.ocfs2/include/dirblocks.h
> index 7b3a2e9..f85974f 100644
> --- a/fsck.ocfs2/include/dirblocks.h
> +++ b/fsck.ocfs2/include/dirblocks.h
> @@ -48,6 +48,10 @@ 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);
> +errcode_t o2fsck_rebuild_indexed_dirs(ocfs2_filesys *fs, struct rb_root *root);
> +errcode_t o2fsck_check_dir_index(struct _o2fsck_state *ost, struct ocfs2_dinode *di);
> 
>  #endif /* __O2FSCK_DIRBLOCKS_H__ */
> 
> diff --git a/fsck.ocfs2/pass1.c b/fsck.ocfs2/pass1.c
> index 0763259..a553656 100644
> --- a/fsck.ocfs2/pass1.c
> +++ b/fsck.ocfs2/pass1.c
> @@ -781,6 +781,53 @@ static int clear_block(ocfs2_filesys *fs,
>  	return 0;
>  }
> 
> +
> +static errcode_t o2fsck_check_dx_dir(o2fsck_state *ost, struct ocfs2_dinode *di)
> +{
> +	errcode_t ret = 0;
> +	char *buf = NULL;
> +	struct ocfs2_dx_root_block *dx_root;
> +	ocfs2_filesys *fs = ost->ost_fs;
> +	struct extent_info ei = {0,};
> +	int changed = 0;
> +
> +	if (!ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(fs->fs_super)))
> +		goto out;
> +
> +	if (!ocfs2_dir_indexed(di))
> +		goto out;
> +
> +	ret = ocfs2_malloc_block(fs->fs_io, &buf);
> +	if (ret)
> +		goto out;
> +
> +	ret = ocfs2_read_dx_root(fs, (uint64_t)di->i_dx_root, buf);
> +	if (ret)
> +		goto out;
> +
> +	dx_root = (struct ocfs2_dx_root_block *)buf;
> +	if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)
> +		goto out;
> +
> +	ret = check_el(ost, &ei, di->i_blkno, &dx_root->dr_list,
> +			ocfs2_extent_recs_per_dx_root(fs->fs_blocksize),
> +			&changed);
> +	if (ret)
> +		goto out;
> +
> +	if (changed) {
> +		ret = ocfs2_write_dx_root(fs, (uint64_t)di->i_dx_root, (char *)dx_root);
> +		if (ret)
> +			com_err(whoami, ret, "while writing an updated "
> +				"dx_root block at %"PRIu64" for inode %"PRIu64,
> +				(uint64_t)di->i_dx_root, (uint64_t)di->i_blkno);
> +	}
> +out:
> +	if (buf)
> +		ocfs2_free(&buf);
> +	return ret;
> +}
> +
>  /*
>   * this verifies i_size and i_clusters for inodes that use i_list to
>   * reference extents of data.
> @@ -836,6 +883,13 @@ static errcode_t o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
>  		goto out;
>  	}
> 
> +	ret = o2fsck_check_dx_dir(ost, di);
> +	if (ret) {
> +		com_err(whoami, ret, "while iterating over the dir indexed "
> +			"tree for directory inode %"PRIu64, (uint64_t)di->i_blkno);
> +		goto out;
> +	}
> +
>  	if (S_ISLNK(di->i_mode))
>  		check_link_data(&vb);
> 
> diff --git a/fsck.ocfs2/pass1b.c b/fsck.ocfs2/pass1b.c
> index 0ea87b4..3ca1d7d 100644
> --- a/fsck.ocfs2/pass1b.c
> +++ b/fsck.ocfs2/pass1b.c
> @@ -902,8 +902,8 @@ static void name_inode(struct dir_scan_context *scan,
>  		pass1c_warn(OCFS2_ET_NO_MEMORY);
>  }
> 
> -static int walk_iterate(struct ocfs2_dir_entry *de, int offset,
> -			int blocksize, char *buf, void *priv_data)
> +static int walk_iterate(struct ocfs2_dir_entry *de, uint64_t blocknr,
> +			int offset, int blocksize, char *buf, void *priv_data)
>  {
>  	struct dir_scan_context *scan = priv_data;
> 
> diff --git a/fsck.ocfs2/pass2.c b/fsck.ocfs2/pass2.c
> index d61c501..9f1adbd 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)
> @@ -833,10 +835,11 @@ next:
>  	}
> 
>  	if (ocfs2_dir_has_trailer(dd->fs, di))
> -		fix_dir_trailer(dd->ost, dbe,
> +		fix_dir_trailer(dd->ost,
> +				dbe,
>  				ocfs2_dir_trailer_from_block(dd->fs,
>  							     dd->dirblock_buf),
> -				&ret_flags);
> +							     &ret_flags);
> 
>  	if (ret_flags & OCFS2_DIRENT_CHANGED) {
>  		if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) {
> @@ -851,15 +854,46 @@ 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) {
> +				com_err(whoami, ret, "while adding block for "
> +					"directory inode %"PRIu64" to rebuild "
> +					"dir index", dbe->e_ino);
> +				goto out;
> +			}
>  		}

The check here should be:

               if (ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super)) &&
                  !(di->i_dyn_features & OCFS2_INLINE_DATA_FL) &&
                  (di->i_dyn_features  & OCFS2_INDEXED_DIR_FL)) {

We don't want to be rebuilding directories which weren't indexed to begin
with.
	--Mark

--
Mark Fasheh



More information about the Ocfs2-tools-devel mailing list