[PATCH 3/5] erofs-utils: lib: switch to per-sb `struct erofs_xattrmgr`
Gao Xiang
hsiangkao at linux.alibaba.com
Tue Sep 30 16:38:45 AEST 2025
It allows the xattr generator to be used for multiple instances.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
include/erofs/internal.h | 2 +
include/erofs/xattr.h | 4 +-
lib/importer.c | 4 +-
lib/super.c | 2 +-
lib/xattr.c | 123 ++++++++++++++++++++++++---------------
5 files changed, 85 insertions(+), 50 deletions(-)
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index f022a0c..e8d8667 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -85,6 +85,7 @@ struct erofs_xattr_prefix_item {
struct erofs_mkfs_dfops;
struct erofs_packed_inode;
+struct erofs_xattrmgr;
struct z_erofs_mgr;
struct erofs_metaboxmgr;
@@ -147,6 +148,7 @@ struct erofs_sb_info {
struct erofs_mkfs_dfops *mkfs_dfops;
#endif
struct erofs_bufmgr *bmgr;
+ struct erofs_xattrmgr *xamgr;
struct z_erofs_mgr *zmgr;
struct erofs_metaboxmgr *m2gr;
struct erofs_packed_inode *packedinode;
diff --git a/include/erofs/xattr.h b/include/erofs/xattr.h
index dc1e3ed..67f6199 100644
--- a/include/erofs/xattr.h
+++ b/include/erofs/xattr.h
@@ -45,7 +45,7 @@ static inline unsigned int xattrblock_offset(struct erofs_inode *vi,
struct erofs_importer;
-void erofs_xattr_init(struct erofs_sb_info *sbi);
+int erofs_xattr_init(struct erofs_sb_info *sbi);
int erofs_scan_file_xattrs(struct erofs_inode *inode);
int erofs_prepare_xattr_ibody(struct erofs_inode *inode, bool noroom);
char *erofs_export_xattr_ibody(struct erofs_inode *inode);
@@ -54,7 +54,6 @@ int erofs_build_shared_xattrs_from_path(struct erofs_sb_info *sbi, const char *p
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);
-void erofs_xattr_prefixes_cleanup(struct erofs_sb_info *sbi);
int erofs_xattr_prefixes_init(struct erofs_sb_info *sbi);
int erofs_setxattr(struct erofs_inode *inode, char *key,
@@ -66,6 +65,7 @@ int erofs_read_xattrs_from_disk(struct erofs_inode *inode);
bool erofs_xattr_prefix_matches(const char *key, unsigned int *index,
unsigned int *len);
+void erofs_xattr_exit(struct erofs_sb_info *sbi);
#ifdef __cplusplus
}
diff --git a/lib/importer.c b/lib/importer.c
index 48d6640..fed7bab 100644
--- a/lib/importer.c
+++ b/lib/importer.c
@@ -48,7 +48,9 @@ int erofs_importer_init(struct erofs_importer *im)
erofs_importer_global_init();
subsys = "xattr";
- erofs_xattr_init(sbi);
+ err = erofs_xattr_init(sbi);
+ if (err)
+ goto out_err;
subsys = "compression";
err = z_erofs_compress_init(im);
diff --git a/lib/super.c b/lib/super.c
index 0540b15..9760265 100644
--- a/lib/super.c
+++ b/lib/super.c
@@ -171,12 +171,12 @@ void erofs_put_super(struct erofs_sb_info *sbi)
free(sbi->devs);
sbi->devs = NULL;
}
- erofs_xattr_prefixes_cleanup(sbi);
if (sbi->bmgr) {
erofs_buffer_exit(sbi->bmgr);
sbi->bmgr = NULL;
}
z_erofs_compress_exit(sbi);
+ erofs_xattr_exit(sbi);
sbi->sb_valid = false;
}
diff --git a/lib/xattr.c b/lib/xattr.c
index ec3eb5e..6e1958b 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -124,20 +124,28 @@ struct erofs_inode_xattr_node {
struct erofs_xattritem *item;
};
-static struct erofs_xattrmgr {
+struct erofs_xattrmgr {
struct list_head hash[1 << 14];
struct erofs_xattritem *shared_xattrs;
unsigned int sharedxattr_count;
-} g_xattrmgr;
+};
-void erofs_xattr_init(struct erofs_sb_info *sbi)
+int erofs_xattr_init(struct erofs_sb_info *sbi)
{
+ struct erofs_xattrmgr *xamgr = sbi->xamgr;
unsigned int i;
- if (g_xattrmgr.hash[0].next)
- return;
- for (i = 0; i < ARRAY_SIZE(g_xattrmgr.hash); ++i)
- init_list_head(&g_xattrmgr.hash[i]);
+ if (xamgr)
+ return 0;
+
+ xamgr = malloc(sizeof(struct erofs_xattrmgr));
+ if (!xamgr)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(xamgr->hash); ++i)
+ init_list_head(&xamgr->hash[i]);
+ sbi->xamgr = xamgr;
+ return 0;
}
static struct erofs_xattr_prefix {
@@ -210,8 +218,10 @@ static unsigned int put_xattritem(struct erofs_xattritem *item)
return 0;
}
-static struct erofs_xattritem *get_xattritem(char *kvbuf, unsigned int len[2])
+static struct erofs_xattritem *get_xattritem(struct erofs_sb_info *sbi,
+ char *kvbuf, unsigned int len[2])
{
+ struct erofs_xattrmgr *xamgr = sbi->xamgr;
struct erofs_xattritem *item;
struct ea_type_node *tnode;
struct list_head *head;
@@ -219,8 +229,8 @@ static struct erofs_xattritem *get_xattritem(char *kvbuf, unsigned int len[2])
hash[0] = BKDRHash(kvbuf, len[0]);
hash[1] = BKDRHash(kvbuf + EROFS_XATTR_KSIZE(len), len[1]);
- hkey = (hash[0] ^ hash[1]) & (ARRAY_SIZE(g_xattrmgr.hash) - 1);
- head = g_xattrmgr.hash + hkey;
+ hkey = (hash[0] ^ hash[1]) & (ARRAY_SIZE(xamgr->hash) - 1);
+ head = xamgr->hash + hkey;
list_for_each_entry(item, head, node) {
if (item->len[0] == len[0] && item->len[1] == len[1] &&
item->hash[0] == hash[0] && item->hash[1] == hash[1] &&
@@ -261,7 +271,8 @@ static struct erofs_xattritem *get_xattritem(char *kvbuf, unsigned int len[2])
return item;
}
-static struct erofs_xattritem *parse_one_xattr(const char *path, const char *key,
+static struct erofs_xattritem *parse_one_xattr(struct erofs_sb_info *sbi,
+ const char *path, const char *key,
unsigned int keylen)
{
ssize_t ret;
@@ -301,7 +312,7 @@ static struct erofs_xattritem *parse_one_xattr(const char *path, const char *key
}
}
- item = get_xattritem(kvbuf, len);
+ item = get_xattritem(sbi, kvbuf, len);
if (!IS_ERR(item))
return item;
ret = PTR_ERR(item);
@@ -310,7 +321,8 @@ out:
return ERR_PTR(ret);
}
-static struct erofs_xattritem *erofs_get_selabel_xattr(const char *srcpath,
+static struct erofs_xattritem *erofs_get_selabel_xattr(struct erofs_sb_info *sbi,
+ const char *srcpath,
mode_t mode)
{
#ifdef HAVE_LIBSELINUX
@@ -353,7 +365,7 @@ static struct erofs_xattritem *erofs_get_selabel_xattr(const char *srcpath,
sprintf(kvbuf, "%s", XATTR_NAME_SECURITY_SELINUX);
memcpy(kvbuf + EROFS_XATTR_KSIZE(len), secontext, len[1]);
freecon(secontext);
- item = get_xattritem(kvbuf, len);
+ item = get_xattritem(sbi, kvbuf, len);
if (IS_ERR(item))
free(kvbuf);
return item;
@@ -374,15 +386,18 @@ static int inode_xattr_add(struct list_head *hlist, struct erofs_xattritem *item
return 0;
}
-static int erofs_xattr_add(struct list_head *ixattrs, struct erofs_xattritem *item)
+static int erofs_xattr_add(struct erofs_sb_info *sbi, struct list_head *ixattrs,
+ struct erofs_xattritem *item)
{
+ struct erofs_xattrmgr *xamgr = sbi->xamgr;
+
if (ixattrs)
return inode_xattr_add(ixattrs, item);
if (item->count == cfg.c_inline_xattr_tolerance + 1) {
- item->next_shared_xattr = g_xattrmgr.shared_xattrs;
- g_xattrmgr.shared_xattrs = item;
- ++g_xattrmgr.sharedxattr_count;
+ item->next_shared_xattr = xamgr->shared_xattrs;
+ xamgr->shared_xattrs = item;
+ ++xamgr->sharedxattr_count;
}
return 0;
}
@@ -397,8 +412,8 @@ static bool erofs_is_skipped_xattr(const char *key)
return false;
}
-static int read_xattrs_from_file(const char *path, mode_t mode,
- struct list_head *ixattrs)
+static int read_xattrs_from_file(struct erofs_sb_info *sbi, const char *path,
+ mode_t mode, struct list_head *ixattrs)
{
ssize_t kllen = erofs_sys_llistxattr(path, NULL, 0);
char *keylst, *key, *klend;
@@ -441,7 +456,7 @@ static int read_xattrs_from_file(const char *path, mode_t mode,
if (erofs_is_skipped_xattr(key))
continue;
- item = parse_one_xattr(path, key, keylen);
+ item = parse_one_xattr(sbi, path, key, keylen);
/* skip inaccessible xattrs */
if (item == ERR_PTR(-ENODATA) || !item) {
erofs_warn("skipped inaccessible xattr %s in %s",
@@ -453,7 +468,7 @@ static int read_xattrs_from_file(const char *path, mode_t mode,
goto err;
}
- ret = erofs_xattr_add(ixattrs, item);
+ ret = erofs_xattr_add(sbi, ixattrs, item);
if (ret < 0)
goto err;
}
@@ -461,11 +476,11 @@ static int read_xattrs_from_file(const char *path, mode_t mode,
out:
/* if some selabel is avilable, need to add right now */
- item = erofs_get_selabel_xattr(path, mode);
+ item = erofs_get_selabel_xattr(sbi, path, mode);
if (IS_ERR(item))
return PTR_ERR(item);
if (item)
- ret = erofs_xattr_add(ixattrs, item);
+ ret = erofs_xattr_add(sbi, ixattrs, item);
return ret;
err:
@@ -476,6 +491,7 @@ err:
int erofs_setxattr(struct erofs_inode *inode, char *key,
const void *value, size_t size)
{
+ struct erofs_sb_info *sbi = inode->sbi;
char *kvbuf;
unsigned int len[2];
struct erofs_xattritem *item;
@@ -490,14 +506,14 @@ int erofs_setxattr(struct erofs_inode *inode, char *key,
memcpy(kvbuf, key, EROFS_XATTR_KSIZE(len));
memcpy(kvbuf + EROFS_XATTR_KSIZE(len), value, size);
- item = get_xattritem(kvbuf, len);
+ item = get_xattritem(sbi, kvbuf, len);
if (IS_ERR(item)) {
free(kvbuf);
return PTR_ERR(item);
}
DBG_BUGON(!item);
- return erofs_xattr_add(&inode->i_xattrs, item);
+ return erofs_xattr_add(sbi, &inode->i_xattrs, item);
}
static void erofs_removexattr(struct erofs_inode *inode, const char *key)
@@ -531,6 +547,7 @@ int erofs_set_origin_xattr(struct erofs_inode *inode)
#ifdef WITH_ANDROID
static int erofs_droid_xattr_set_caps(struct erofs_inode *inode)
{
+ struct erofs_sb_info *sbi = inode->sbi;
const u64 capabilities = inode->capabilities;
char *kvbuf;
unsigned int len[2];
@@ -555,14 +572,14 @@ static int erofs_droid_xattr_set_caps(struct erofs_inode *inode)
caps.data[1].inheritable = 0;
memcpy(kvbuf + EROFS_XATTR_KSIZE(len), &caps, len[1]);
- item = get_xattritem(kvbuf, len);
+ item = get_xattritem(sbi, kvbuf, len);
if (IS_ERR(item)) {
free(kvbuf);
return PTR_ERR(item);
}
DBG_BUGON(!item);
- return erofs_xattr_add(&inode->i_xattrs, item);
+ return erofs_xattr_add(sbi, &inode->i_xattrs, item);
}
#else
static int erofs_droid_xattr_set_caps(struct erofs_inode *inode)
@@ -580,7 +597,8 @@ int erofs_scan_file_xattrs(struct erofs_inode *inode)
if (cfg.c_inline_xattr_tolerance < 0)
return 0;
- ret = read_xattrs_from_file(inode->i_srcpath, inode->i_mode, ixattrs);
+ ret = read_xattrs_from_file(inode->sbi, inode->i_srcpath,
+ inode->i_mode, ixattrs);
if (ret < 0)
return ret;
@@ -705,7 +723,8 @@ out:
return ret;
}
-static int erofs_count_all_xattrs_from_path(const char *path)
+static int erofs_count_all_xattrs_from_path(struct erofs_sb_info *sbi,
+ const char *path)
{
int ret;
DIR *_dir;
@@ -732,8 +751,7 @@ static int erofs_count_all_xattrs_from_path(const char *path)
if (!dp)
break;
- if (is_dot_dotdot(dp->d_name) ||
- !strncmp(dp->d_name, "lost+found", strlen("lost+found")))
+ if (is_dot_dotdot(dp->d_name))
continue;
ret = snprintf(buf, PATH_MAX, "%s/%s", path, dp->d_name);
@@ -750,14 +768,14 @@ static int erofs_count_all_xattrs_from_path(const char *path)
goto fail;
}
- ret = read_xattrs_from_file(buf, st.st_mode, NULL);
+ ret = read_xattrs_from_file(sbi, buf, st.st_mode, NULL);
if (ret)
goto fail;
if (!S_ISDIR(st.st_mode))
continue;
- ret = erofs_count_all_xattrs_from_path(buf);
+ ret = erofs_count_all_xattrs_from_path(sbi, buf);
if (ret)
goto fail;
}
@@ -770,13 +788,13 @@ fail:
return ret;
}
-static void erofs_cleanxattrs(bool sharedxattrs)
+static void erofs_cleanxattrs(struct erofs_xattrmgr *xamgr, bool sharedxattrs)
{
struct erofs_xattritem *item, *n;
unsigned int i;
- for (i = 0; i < ARRAY_SIZE(g_xattrmgr.hash); ++i) {
- list_for_each_entry_safe(item, n, g_xattrmgr.hash + i, node) {
+ for (i = 0; i < ARRAY_SIZE(xamgr->hash); ++i) {
+ list_for_each_entry_safe(item, n, xamgr->hash + i, node) {
if (sharedxattrs && item->shared_xattr_id >= 0)
continue;
list_del(&item->node);
@@ -787,7 +805,7 @@ static void erofs_cleanxattrs(bool sharedxattrs)
if (sharedxattrs)
return;
- g_xattrmgr.sharedxattr_count = 0;
+ xamgr->sharedxattr_count = 0;
}
static int comp_shared_xattritem(const void *a, const void *b)
@@ -921,6 +939,7 @@ static void erofs_write_xattr_entry(char *buf, struct erofs_xattritem *item)
int erofs_build_shared_xattrs_from_path(struct erofs_sb_info *sbi, const char *path)
{
+ struct erofs_xattrmgr *xamgr = sbi->xamgr;
struct erofs_xattritem *item, *n, **sorted_n;
unsigned int sharedxattr_count, p, i;
struct erofs_buffer_head *bh;
@@ -934,15 +953,15 @@ int erofs_build_shared_xattrs_from_path(struct erofs_sb_info *sbi, const char *p
cfg.c_inline_xattr_tolerance == INT_MAX)
return 0;
- if (g_xattrmgr.sharedxattr_count) {
+ if (xamgr->sharedxattr_count) {
DBG_BUGON(1);
return -EINVAL;
}
- ret = erofs_count_all_xattrs_from_path(path);
+ ret = erofs_count_all_xattrs_from_path(sbi, path);
if (ret)
return ret;
- sharedxattr_count = g_xattrmgr.sharedxattr_count;
+ sharedxattr_count = xamgr->sharedxattr_count;
if (!sharedxattr_count)
goto out;
@@ -951,10 +970,10 @@ int erofs_build_shared_xattrs_from_path(struct erofs_sb_info *sbi, const char *p
return -ENOMEM;
i = 0;
- while (g_xattrmgr.shared_xattrs) {
- item = g_xattrmgr.shared_xattrs;
+ while (xamgr->shared_xattrs) {
+ item = xamgr->shared_xattrs;
sorted_n[i++] = item;
- g_xattrmgr.shared_xattrs = item->next_shared_xattr;
+ xamgr->shared_xattrs = item->next_shared_xattr;
shared_xattrs_size = erofs_next_xattr_align(shared_xattrs_size,
item);
}
@@ -989,14 +1008,14 @@ int erofs_build_shared_xattrs_from_path(struct erofs_sb_info *sbi, const char *p
item->shared_xattr_id = (off + p) / sizeof(__le32);
p = erofs_next_xattr_align(p, item);
}
- g_xattrmgr.shared_xattrs = sorted_n[0];
+ xamgr->shared_xattrs = sorted_n[0];
free(sorted_n);
bh->op = &erofs_drop_directly_bhops;
ret = erofs_dev_write(sbi, buf, erofs_btell(bh, false), shared_xattrs_size);
free(buf);
erofs_bdrop(bh, false);
out:
- erofs_cleanxattrs(true);
+ erofs_cleanxattrs(xamgr, true);
return ret;
}
@@ -1726,3 +1745,15 @@ out:
erofs_xattr_prefixes_cleanup(sbi);
return ret;
}
+
+void erofs_xattr_exit(struct erofs_sb_info *sbi)
+{
+ struct erofs_xattrmgr *xamgr = sbi->xamgr;
+
+ erofs_xattr_prefixes_cleanup(sbi);
+ if (!xamgr)
+ return;
+ erofs_cleanxattrs(xamgr, false);
+ sbi->xamgr = NULL;
+ free(xamgr);
+}
--
2.43.5
More information about the Linux-erofs
mailing list