[Ocfs2-tools-devel] [PATCH 6/7] libocfs2: iterate all xattr entries of a file
Joel Becker
Joel.Becker at oracle.com
Tue Nov 24 17:14:30 PST 2009
On Tue, Oct 20, 2009 at 04:42:16PM +0800, Tiger Yang wrote:
> This patch add iteration function for all xattr entries
> related of a file. ocfs2_xattr_iterate will call the callback
> function on each xattr entry.
>
> Signed-off-by: Tiger Yang <tiger.yang at oracle.com>
> ---
> include/ocfs2/ocfs2.h | 8 ++
> libocfs2/xattr.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 198 insertions(+), 0 deletions(-)
>
> diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
> index 20d391e..f9e5c5a 100644
> --- a/include/ocfs2/ocfs2.h
> +++ b/include/ocfs2/ocfs2.h
> @@ -1264,6 +1264,14 @@ errcode_t ocfs2_block_iterate_inode(ocfs2_filesys *fs,
> void *priv_data),
> void *priv_data);
>
> +#define OCFS2_XATTR_ABORT 0x01
> +#define OCFS2_XATTR_ERROR 0x02
> +errcode_t ocfs2_xattr_iterate(ocfs2_cached_inode *ci,
> + int (*func)(ocfs2_cached_inode *ci,
> + struct ocfs2_xattr_entry *xe,
> + void *priv_data),
> + void *priv_data);
> +
> uint32_t ocfs2_xattr_uuid_hash(unsigned char *uuid);
> uint32_t ocfs2_xattr_name_hash(uint32_t uuid_hash, const char *name,
> int name_len);
> diff --git a/libocfs2/xattr.c b/libocfs2/xattr.c
> index d3285c8..dfc3c99 100644
> --- a/libocfs2/xattr.c
> +++ b/libocfs2/xattr.c
> @@ -611,6 +611,165 @@ static int ocfs2_xattr_has_space_inline(ocfs2_cached_inode *ci,
> return 0;
> }
>
> +static errcode_t ocfs2_xattr_iterate_entries(ocfs2_cached_inode *ci,
> + struct ocfs2_xattr_header *header,
> + int (*func)(ocfs2_cached_inode *ci,
> + struct ocfs2_xattr_entry *xe,
> + void *priv_data),
> + void *priv_data)
> +{
> + int i;
> + struct ocfs2_xattr_entry *entry = NULL;
> + errcode_t ret = 0;
> +
> + for (i = 0 ; i < header->xh_count; i++) {
> + entry = &header->xh_entries[i];
> + ret = func(ci, entry, priv_data);
> + if (ret == OCFS2_XATTR_ABORT || ret == OCFS2_XATTR_ERROR)
> + return ret;
This return code should be iret and like extent_iterate it can
be the bitwise orr of the flags. So:
static int ocfs2_xattr_iterate_entries(...)
{
...
iret = func(ci, entry, priv_data);
if (iret & (OCFS2_XATTR_ABORT | OCFS2_XATTR_ERROR))
break;
}
return iret;
}
> +static errcode_t ocfs2_xattr_iterate_ibody(ocfs2_cached_inode *ci,
> + int (*func)(ocfs2_cached_inode *ci,
> + struct ocfs2_xattr_entry *xe,
> + void *priv_data),
> + void *priv_data)
Again returning iret here.
> +static errcode_t ocfs2_xattr_iterate_bucket(ocfs2_cached_inode *ci,
> + uint64_t blkno,
> + uint32_t clusters,
> + int (*func)(ocfs2_cached_inode *ci,
> + struct ocfs2_xattr_entry *xe,
> + void *priv_data),
> + void *priv_data)
> +{
> + int i;
> + errcode_t ret = 0;
> + char *bucket = NULL;
> + struct ocfs2_xattr_header *xh;
> + ocfs2_filesys *fs = ci->ci_fs;
> + int blk_per_bucket = ocfs2_blocks_per_xattr_bucket(fs);
> + uint32_t bpc = ocfs2_xattr_buckets_per_cluster(fs);
> + uint32_t num_buckets = clusters * bpc;
> +
> + ret = ocfs2_malloc_blocks(fs->fs_io, blk_per_bucket, &bucket);
> + if (ret)
> + goto out;
This also needs to return iret.
You need to be passing a context in here. If you get an
errcode_t off a subfunction (ocfs2_malloc_blocks,
ocfs2_read_xattr_bucket(), etc) you store it on the context and then
set ire |= OCFS2_XATTR_ERROR. See extents.c/extent_iterate_eb() for an
example of this.
The same goes for all of these subfunctions.
> +errcode_t ocfs2_xattr_iterate(ocfs2_cached_inode *ci,
> + int (*func)(ocfs2_cached_inode *ci,
> + struct ocfs2_xattr_entry *xe,
> + void *priv_data),
> + void *priv_data)
> +{
> + errcode_t ret = 0;
> + struct ocfs2_super_block *sb = OCFS2_RAW_SB(ci->ci_fs->fs_super);
> + struct ocfs2_dinode *di = ci->ci_inode;
> +
> + if (!(sb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_XATTR))
> + return OCFS2_ET_UNSUPP_FEATURE;
> + if (!(di->i_dyn_features & OCFS2_HAS_XATTR_FL))
> + return OCFS2_ET_XATTR_NODATA;
> +
> + ret = ocfs2_xattr_iterate_ibody(ci, func, priv_data);
> + if (ret)
> + ret = ocfs2_xattr_iterate_block(ci, func, priv_data);
This is totally incorrect. "If there is an error, go look at
the block"? What you want is:
...
ctxt.ci = ci;
ctxt.func = func;
ctxt.priv_data = priv_data;
ctxt.errcode = 0;
iret = ocfs2_xattr_iterate_ibody(&ctxt);
if (!(iret & (OCFS2_XATTR_ABORT | OCFS2_XATTR_ERROR)))
iret = ocfs2_xattr_iterate_block(&ctxt);
if (iret & OCFS2_XATTR_ERROR)
ret = ctxt.errcode;
return ret;
Joel
--
"What does it say about a society's priorities when the time you
spend in meetings on Monday is greater than the total number of
hours you spent sleeping over the weekend?"
- Nat Friedman
Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
More information about the Ocfs2-tools-devel
mailing list