[PATCH 1/2] erofs-utils: lib: introduce prefix-aware erofs_setxattr()

Hongbo Li lihongbo22 at huawei.com
Mon Dec 29 23:52:39 AEDT 2025



On 2025/12/29 15:49, Gao Xiang wrote:
> Allows users to specify a predefined prefix for xattr names.
> 
> Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>

Reviewed-by: Hongbo Li <lihongbo22 at huawei.com>

Thanks,
Hongbo

> ---
>   include/erofs/xattr.h |  5 +++--
>   lib/tar.c             |  2 +-
>   lib/xattr.c           | 45 +++++++++++++++++++++++++++++++++----------
>   3 files changed, 39 insertions(+), 13 deletions(-)
> 
> diff --git a/include/erofs/xattr.h b/include/erofs/xattr.h
> index 83aca44f8e44..941bed778956 100644
> --- a/include/erofs/xattr.h
> +++ b/include/erofs/xattr.h
> @@ -36,9 +36,10 @@ int erofs_xattr_insert_name_prefix(const char *prefix);
>   void erofs_xattr_cleanup_name_prefixes(void);
>   int erofs_xattr_flush_name_prefixes(struct erofs_importer *im, bool plain);
>   int erofs_xattr_prefixes_init(struct erofs_sb_info *sbi);
> -
> -int erofs_setxattr(struct erofs_inode *inode, char *key,
> +int erofs_setxattr(struct erofs_inode *inode, int index, const char *name,
>   		   const void *value, size_t size);
> +int erofs_vfs_setxattr(struct erofs_inode *inode, const char *name,
> +		       const void *value, size_t size);
>   int erofs_set_opaque_xattr(struct erofs_inode *inode);
>   void erofs_clear_opaque_xattr(struct erofs_inode *inode);
>   int erofs_set_origin_xattr(struct erofs_inode *inode);
> diff --git a/lib/tar.c b/lib/tar.c
> index 16da593c3df1..8aa90c7dc0d4 100644
> --- a/lib/tar.c
> +++ b/lib/tar.c
> @@ -411,7 +411,7 @@ int tarerofs_apply_xattrs(struct erofs_inode *inode, struct list_head *xattrs)
>   		item->kv[item->namelen] = '\0';
>   		erofs_dbg("Recording xattr(%s)=\"%s\" (of %u bytes) to file %s",
>   			  item->kv, v, vsz, inode->i_srcpath);
> -		ret = erofs_setxattr(inode, item->kv, v, vsz);
> +		ret = erofs_vfs_setxattr(inode, item->kv, v, vsz);
>   		if (ret == -ENODATA)
>   			erofs_err("Failed to set xattr(%s)=%s to file %s",
>   				  item->kv, v, inode->i_srcpath);
> diff --git a/lib/xattr.c b/lib/xattr.c
> index 96be0b1bede5..b6b1a5e600fb 100644
> --- a/lib/xattr.c
> +++ b/lib/xattr.c
> @@ -179,7 +179,7 @@ static struct erofs_xattr_prefix {
>   	const char *prefix;
>   	unsigned int prefix_len;
>   } xattr_types[] = {
> -	[EROFS_XATTR_INDEX_USER] = {
> +	[0] = {""}, [EROFS_XATTR_INDEX_USER] = {
>   		XATTR_USER_PREFIX,
>   		XATTR_USER_PREFIX_LEN
>   	}, [EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] = {
> @@ -501,22 +501,41 @@ err:
>   	return ret;
>   }
>   
> -int erofs_setxattr(struct erofs_inode *inode, char *key,
> -		   const void *value, size_t size)
> +int erofs_setxattr(struct erofs_inode *inode, int index,
> +		   const char *name, const void *value, size_t size)
>   {
>   	struct erofs_sb_info *sbi = inode->sbi;
> -	char *kvbuf;
> -	unsigned int len[2];
>   	struct erofs_xattritem *item;
> +	struct erofs_xattr_prefix *prefix = NULL;
> +	struct ea_type_node *tnode;
> +	unsigned int len[2];
> +	int prefix_len;
> +	char *kvbuf;
>   
> -	len[0] = strlen(key);
> +	if (index & EROFS_XATTR_LONG_PREFIX) {
> +		list_for_each_entry(tnode, &ea_name_prefixes, list) {
> +			if (index == tnode->index) {
> +				prefix = &tnode->type;
> +				break;
> +			}
> +		}
> +	} else if (index < ARRAY_SIZE(xattr_types)) {
> +		prefix = &xattr_types[index];
> +	}
> +
> +	if (!prefix)
> +		return -EINVAL;
> +
> +	prefix_len = prefix->prefix_len;
> +	len[0] = prefix_len + strlen(name);
>   	len[1] = size;
>   
>   	kvbuf = malloc(EROFS_XATTR_KVSIZE(len));
>   	if (!kvbuf)
>   		return -ENOMEM;
>   
> -	memcpy(kvbuf, key, EROFS_XATTR_KSIZE(len));
> +	memcpy(kvbuf, prefix->prefix, prefix_len);
> +	memcpy(kvbuf + prefix_len, name, EROFS_XATTR_KSIZE(len) - prefix_len);
>   	memcpy(kvbuf + EROFS_XATTR_KSIZE(len), value, size);
>   
>   	item = get_xattritem(sbi, kvbuf, len);
> @@ -528,6 +547,12 @@ int erofs_setxattr(struct erofs_inode *inode, char *key,
>   	return erofs_inode_xattr_add(&inode->i_xattrs, item);
>   }
>   
> +int erofs_vfs_setxattr(struct erofs_inode *inode, const char *name,
> +		       const void *value, size_t size)
> +{
> +	return erofs_setxattr(inode, 0, name, value, size);
> +}
> +
>   static void erofs_removexattr(struct erofs_inode *inode, const char *key)
>   {
>   	struct erofs_inode_xattr_node *node, *n;
> @@ -543,7 +568,7 @@ static void erofs_removexattr(struct erofs_inode *inode, const char *key)
>   
>   int erofs_set_opaque_xattr(struct erofs_inode *inode)
>   {
> -	return erofs_setxattr(inode, OVL_XATTR_OPAQUE, "y", 1);
> +	return erofs_vfs_setxattr(inode, OVL_XATTR_OPAQUE, "y", 1);
>   }
>   
>   void erofs_clear_opaque_xattr(struct erofs_inode *inode)
> @@ -553,7 +578,7 @@ void erofs_clear_opaque_xattr(struct erofs_inode *inode)
>   
>   int erofs_set_origin_xattr(struct erofs_inode *inode)
>   {
> -	return erofs_setxattr(inode, OVL_XATTR_ORIGIN, NULL, 0);
> +	return erofs_vfs_setxattr(inode, OVL_XATTR_ORIGIN, NULL, 0);
>   }
>   
>   #ifdef WITH_ANDROID
> @@ -671,7 +696,7 @@ int erofs_read_xattrs_from_disk(struct erofs_inode *inode)
>   			continue;
>   		}
>   
> -		ret = erofs_setxattr(inode, key, value, size);
> +		ret = erofs_vfs_setxattr(inode, key, value, size);
>   		free(value);
>   		if (ret)
>   			break;


More information about the Linux-erofs mailing list