[Ocfs2-tools-devel] [PATCH 01/15] dx_dirs v11: Add library support for directory indexing

Tao Ma tao.ma at oracle.com
Thu Apr 22 23:47:51 PDT 2010


Hi Coly/Mark,
	Sorry for the delay.

Coly Li wrote:
> diff --git a/libocfs2/dir_iterate.c b/libocfs2/dir_iterate.c
> index 00c8d16..1064d9f 100644
> --- a/libocfs2/dir_iterate.c
> +++ b/libocfs2/dir_iterate.c
> @@ -307,6 +307,161 @@ int ocfs2_process_dir_block(ocfs2_filesys *fs,
>  	return 0;
>  }
>  
> +struct dx_iterator_data {
> +	int (*dx_func)(ocfs2_filesys *fs,
> +		       struct ocfs2_dx_entry_list *entry_list,
> +		       struct ocfs2_dx_root_block *dx_root,
> +		       struct ocfs2_dx_leaf *dx_leaf,
> +		       void *priv_data);
> +	void *dx_priv_data;
> +	char *leaf_buf;
> +	struct ocfs2_dx_root_block *dx_root;
> +};
> +
> +static int dx_iterator(ocfs2_filesys *fs,
> +		       struct ocfs2_extent_rec *rec,
> +		       int tree_depth,
> +		       uint32_t ccount,
> +		       uint64_t ref_blkno,
> +		       int ref_recno,
> +		       void *priv_data)
> +{
> +	int ret, i;
> +	struct ocfs2_dx_leaf *dx_leaf;
> +	struct dx_iterator_data *iter = priv_data;
> +	uint64_t blkno, count;
> +
> +	count = ocfs2_clusters_to_blocks(fs, rec->e_leaf_clusters);
> +
> +	blkno = rec->e_blkno;
> +	for (i = 0; i < count; i++) {
> +		ret = ocfs2_read_dx_leaf(fs, blkno, iter->leaf_buf);
> +		if (ret)
> +			return ret;
I noticed that this function is actually called by extent_iterate_el. So 
I guess we'd better store 'ret' here in dx_iterator_data and return 
OCFS2_EXTENT_ERROR. That way we can stop iteration immediately. Return 
an errcode_t here can't work.
> +
> +		dx_leaf = (struct ocfs2_dx_leaf *)iter->leaf_buf;
> +		iter->dx_func(fs, &dx_leaf->dl_list, iter->dx_root, dx_leaf,
> +			      iter->dx_priv_data);
We will not take the return value into consideration here. Do we have a 
plan that we will support some return values like OCFS2_CHAIN_ABORT so 
that we can stop the iteration by the given callback functions?
> +
> +		blkno++;
> +	}
> +
> +	return 0;
> +}
> +
> +extern errcode_t ocfs2_dx_entries_iterate(ocfs2_filesys *fs,
> +			struct ocfs2_dinode *dir,
> +			int flags,
> +			int (*func)(ocfs2_filesys *fs,
> +				    struct ocfs2_dx_entry_list *entry_list,
> +				    struct ocfs2_dx_root_block *dx_root,
> +				    struct ocfs2_dx_leaf *dx_leaf,
> +				    void *priv_data),
> +			void *priv_data)
> +{
> +	errcode_t ret = 0;
> +	struct ocfs2_dx_root_block *dx_root;
> +	uint64_t dx_blkno;
> +	char *buf = NULL, *eb_buf = NULL, *leaf_buf = NULL;
> +	struct dx_iterator_data data;
> +
> +	if (!S_ISDIR(dir->i_mode) && !ocfs2_dir_indexed(dir)) {
> +		ret = 0;
No need to set ret here.
> +		goto out;
> +	}
> +
> +	ret = ocfs2_malloc_block(fs->fs_io, &buf);
> +	if (ret)
> +		goto out;
> +
> +	dx_blkno = (uint64_t) dir->i_dx_root;
> +
> +	ret = ocfs2_read_dx_root(fs, dx_blkno, buf);
> +	if (ret)
> +		goto out;
> +
> +	dx_root = (struct ocfs2_dx_root_block *)buf;
> +
> +	if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE) {
> +		func(fs, &dx_root->dr_entries, dx_root, NULL, priv_data);
> +		ret = 0;
> +		goto out;
> +	}
> +
> +	ret = ocfs2_malloc_block(fs->fs_io, &eb_buf);
> +	if (ret)
> +		goto out;
> +
> +	ret = ocfs2_malloc_block(fs->fs_io, &leaf_buf);
> +	if (ret)
> +		goto out;
> +
> +	data.dx_func = func;
> +	data.dx_priv_data = priv_data;
> +	data.leaf_buf = leaf_buf;
> +	data.dx_root = dx_root;
> +	ret = ocfs2_extent_iterate_dx_root(fs, dx_root,
> +					   OCFS2_EXTENT_FLAG_DATA_ONLY, eb_buf,
> +					   dx_iterator, &data);
> +
> +out:
> +	if (buf)
> +		ocfs2_free(&buf);
> +	if (eb_buf)
> +		ocfs2_free(&eb_buf);
> +	if (leaf_buf)
> +		ocfs2_free(&leaf_buf);
> +	return ret;
> +}
> +
> +extern errcode_t ocfs2_dx_frees_iterate(ocfs2_filesys *fs,
> +			struct ocfs2_dinode *dir,
> +			struct ocfs2_dx_root_block *dx_root,
> +			int flags,
> +			int (*func)(ocfs2_filesys *fs,
> +				    uint64_t blkno,
> +				    struct ocfs2_dir_block_trailer *trailer,
> +				    char *dirblock,
> +				    void *priv_data),
> +			void *priv_data)
> +{
> +	errcode_t ret = 0;
> +	uint64_t blkno;
> +	char *buf = NULL;
> +	struct ocfs2_dir_block_trailer *trailer;
> +
> +	if (!S_ISDIR(dir->i_mode) || !(ocfs2_dir_indexed(dir))) {
> +		ret = 0;
No need to set 'ret' here.
> +		goto out;
> +	}
> +
> +	if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE) {
> +		ret = 0;
ditto.
> +		goto out;
> +	}
> +
> +	ret = ocfs2_malloc_block(fs->fs_io, &buf);
> +	if (ret)
> +		goto out;
> +
> +	blkno = dx_root->dr_free_blk;
> +	while (blkno) {
> +		ret = ocfs2_read_dir_block(fs, dir, blkno, buf);
> +		if (ret)
> +			goto out;
> +
> +		trailer = ocfs2_dir_trailer_from_block(fs, buf);
> +
> +		func(fs, blkno, trailer, buf, priv_data);
> +
> +		blkno = trailer->db_free_next;
> +	}
> +
> +out:
> +	if (buf)
> +		ocfs2_free(&buf);
> +	return ret;
> +}
<snip>
> +errcode_t ocfs2_extent_iterate_dx_root(ocfs2_filesys *fs,
> +				       struct ocfs2_dx_root_block *dx_root,
> +				       int flags,
> +				       char *block_buf,
> +				       int (*func)(ocfs2_filesys *fs,
> +						   struct ocfs2_extent_rec *rec,
> +						   int tree_depth,
> +						   uint32_t ccount,
> +						   uint64_t ref_blkno,
> +						   int ref_recno,
> +						   void *priv_data),
> +				       void *priv_data)
> +{
> +	int i;
> +	int iret = 0;
> +	struct ocfs2_extent_list *el;
> +	errcode_t ret;
> +	struct extent_context ctxt;
> +
> +	if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)
> +		return OCFS2_ET_INODE_CANNOT_BE_ITERATED;
> +
> +	el = &dx_root->dr_list;
> +	if (el->l_tree_depth) {
> +		ret = ocfs2_malloc0(sizeof(char *) * el->l_tree_depth,
> +				    &ctxt.eb_bufs);
> +		if (ret)
> +			goto out;
> +
> +		if (block_buf) {
> +			ctxt.eb_bufs[0] = block_buf;
> +		} else {
> +			ret = ocfs2_malloc0(fs->fs_blocksize *
> +					    el->l_tree_depth,
> +					    &ctxt.eb_bufs[0]);
> +			if (ret)
> +				goto out_eb_bufs;
> +		}
> +
> +		for (i = 1; i < el->l_tree_depth; i++) {
> +			ctxt.eb_bufs[i] = ctxt.eb_bufs[0] +
> +				i * fs->fs_blocksize;
> +		}
> +	}
> +	else
> +		ctxt.eb_bufs = NULL;
> +
> +	ctxt.fs = fs;
> +	ctxt.func = func;
> +	ctxt.priv_data = priv_data;
> +	ctxt.flags = flags;
> +	ctxt.ccount = 0;
> +	ctxt.last_eb_blkno = 0;
> +	ctxt.last_eb_cpos = 0;
> +
> +	ret = 0;
> +	iret |= extent_iterate_el(el, 0, &ctxt);
> +	if (iret & OCFS2_EXTENT_ERROR)
> +		ret = ctxt.errcode;
> +
> +	if (iret & OCFS2_EXTENT_ABORT)
> +		goto out_abort;
> +
> +	/* we can only trust ctxt.last_eb_blkno if we walked the whole tree */
> +	if (dx_root->dr_last_eb_blk != ctxt.last_eb_blkno) {
> +		dx_root->dr_last_eb_blk = ctxt.last_eb_blkno;
> +		iret |= OCFS2_EXTENT_CHANGED;
> +	}
> +
> +out_abort:
> +#if 0
> +	/*
> +	 * This block needs to be fixed up for write support.
> +	 */
> +	if (!ret && (iret & OCFS2_EXTENT_CHANGED))
> +		ret = ocfs2_write_inode(fs, inode->i_blkno, (char *)inode);
> +#endif
> +
> +out_eb_bufs:
> +	if (ctxt.eb_bufs) {
hey, this field isn't set to NULL at the beginning.
> +		if (!block_buf && ctxt.eb_bufs[0])
> +			ocfs2_free(&ctxt.eb_bufs[0]);
> +		ocfs2_free(&ctxt.eb_bufs);
> +	}
> +
> +out:
> +	return ret;
> +}
> +
>  errcode_t ocfs2_extent_iterate(ocfs2_filesys *fs,
>  			       uint64_t blkno,
>  			       int flags,
> diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
> index 7021dba..0974fb6 100644
> --- a/libocfs2/feature_string.c
> +++ b/libocfs2/feature_string.c
> @@ -89,7 +89,8 @@ static ocfs2_fs_options feature_level_defaults[] = {
>  	 OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
>  	 OCFS2_FEATURE_INCOMPAT_META_ECC |
>  	 OCFS2_FEATURE_INCOMPAT_XATTR |
> -	 OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE,
> +	 OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE |
> +	 OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS,
>  	 OCFS2_FEATURE_RO_COMPAT_UNWRITTEN |
>  	 OCFS2_FEATURE_RO_COMPAT_USRQUOTA |
>  	 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA }, /* OCFS2_FEATURE_LEVEL_MAX_FEATURES */
> @@ -165,6 +166,11 @@ static struct fs_feature_flags ocfs2_supported_features[] = {
>  		{0, OCFS2_FEATURE_INCOMPAT_XATTR, 0},
>  		{0, OCFS2_FEATURE_INCOMPAT_XATTR, 0},
>  	},
> + 	{
> +		"indexed-dirs",
> +		{0, OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS, 0},
> +		{0, OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS, 0},
> +	},
>  	{
>  		"usrquota",
>  		{0, 0, OCFS2_FEATURE_RO_COMPAT_USRQUOTA},
> @@ -247,6 +253,10 @@ static struct feature_name ocfs2_feature_names[] = {
>  		.fn_name = "xattr",
>  		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_XATTR, 0},
>  	},
> + 	{
> +		.fn_name = "IndexedDirs",
> +		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS, 0},
I remembered that now we required both featurn strings should have the 
same name. Here one is "indexed-dirs", the other is "IndexedDirs".

Regards,
Tao



More information about the Ocfs2-tools-devel mailing list