[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