[PATCH v2 1/7] erofs-utils: lib: introduce liberofs_global_{init,exit}
Gao Xiang
hsiangkao at linux.alibaba.com
Tue Aug 19 12:20:28 AEST 2025
Currently, the codebase only supports a single instance during
the entire running time. This will be extended to allow 3rd-party
applications to formally use liberofs with multiple instances
simultaneously. Therefore, it is necessary to separate global
initialization from per-instance initialization.
Another point is that libcurl will be used for other remote
backends, so it also needs to be separated from the current S3
backend.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
v2:
- update the commit message;
- fix non-MT compile error.
include/erofs/internal.h | 3 ++
include/erofs/lock.h | 6 ++++
lib/Makefile.am | 5 ++--
lib/global.c | 55 ++++++++++++++++++++++++++++++++++
lib/liberofs_s3.h | 1 +
lib/remotes/s3.c | 65 ++++++++++++++++++----------------------
mkfs/main.c | 22 +++++++-------
7 files changed, 109 insertions(+), 48 deletions(-)
create mode 100644 lib/global.c
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index e9b9099..92e83fd 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -426,6 +426,9 @@ struct erofs_map_dev {
unsigned int m_deviceid;
};
+int liberofs_global_init(void);
+void liberofs_global_exit(void);
+
/* super.c */
int erofs_read_superblock(struct erofs_sb_info *sbi);
void erofs_put_super(struct erofs_sb_info *sbi);
diff --git a/include/erofs/lock.h b/include/erofs/lock.h
index f7a4b47..c6e3093 100644
--- a/include/erofs/lock.h
+++ b/include/erofs/lock.h
@@ -16,6 +16,9 @@ static inline void erofs_mutex_init(erofs_mutex_t *lock)
#define erofs_mutex_lock pthread_mutex_lock
#define erofs_mutex_unlock pthread_mutex_unlock
+#define EROFS_DEFINE_MUTEX(lock) \
+ erofs_mutex_t lock = PTHREAD_MUTEX_INITIALIZER
+
typedef pthread_rwlock_t erofs_rwsem_t;
static inline void erofs_init_rwsem(erofs_rwsem_t *lock)
@@ -33,6 +36,9 @@ static inline void erofs_mutex_init(erofs_mutex_t *lock) {}
static inline void erofs_mutex_lock(erofs_mutex_t *lock) {}
static inline void erofs_mutex_unlock(erofs_mutex_t *lock) {}
+#define EROFS_DEFINE_MUTEX(lock) \
+ erofs_mutex_t lock = {}
+
typedef struct {} erofs_rwsem_t;
static inline void erofs_init_rwsem(erofs_rwsem_t *lock) {}
static inline void erofs_down_read(erofs_rwsem_t *lock) {}
diff --git a/lib/Makefile.am b/lib/Makefile.am
index b079897..a3972b1 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -29,7 +29,8 @@ noinst_HEADERS = $(top_srcdir)/include/erofs_fs.h \
$(top_srcdir)/include/erofs/rebuild.h \
$(top_srcdir)/lib/liberofs_private.h \
$(top_srcdir)/lib/liberofs_xxhash.h \
- $(top_srcdir)/lib/liberofs_metabox.h
+ $(top_srcdir)/lib/liberofs_metabox.h \
+ $(top_srcdir)/lib/liberofs_s3.h
noinst_HEADERS += compressor.h
liberofs_la_SOURCES = config.c io.c cache.c super.c inode.c xattr.c exclude.c \
@@ -37,7 +38,7 @@ liberofs_la_SOURCES = config.c io.c cache.c super.c inode.c xattr.c exclude.c \
compress_hints.c hashmap.c sha256.c blobchunk.c dir.c \
fragments.c dedupe.c uuid_unparse.c uuid.c tar.c \
block_list.c rebuild.c diskbuf.c bitops.c dedupe_ext.c \
- vmdk.c metabox.c
+ vmdk.c metabox.c global.c
liberofs_la_CFLAGS = -Wall ${libuuid_CFLAGS} -I$(top_srcdir)/include
if ENABLE_LZ4
diff --git a/lib/global.c b/lib/global.c
new file mode 100644
index 0000000..2f9abd6
--- /dev/null
+++ b/lib/global.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
+/*
+ * Copyright (C) 2025 Alibaba Cloud
+ */
+#include "erofs/lock.h"
+#ifdef HAVE_CURL_CURL_H
+#include <curl/curl.h>
+#endif
+#ifdef HAVE_LIBXML_PARSER_H
+#include <libxml/parser.h>
+#endif
+#include "erofs/err.h"
+#include "erofs/config.h"
+
+static EROFS_DEFINE_MUTEX(erofs_global_mutex);
+static bool erofs_global_curl_initialized;
+
+int liberofs_global_init(void)
+{
+ int err = 0;
+
+ erofs_mutex_lock(&erofs_global_mutex);
+ erofs_init_configure();
+#ifdef S3EROFS_ENABLED
+ xmlInitParser();
+#endif
+#ifdef HAVE_LIBCURL
+ if (!erofs_global_curl_initialized) {
+ if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
+ err = -EFAULT;
+ goto out_unlock;
+ }
+ erofs_global_curl_initialized = true;
+ }
+out_unlock:
+#endif
+ erofs_mutex_unlock(&erofs_global_mutex);
+ return err;
+}
+
+void liberofs_global_exit(void)
+{
+ erofs_mutex_lock(&erofs_global_mutex);
+#ifdef HAVE_LIBCURL
+ if (erofs_global_curl_initialized) {
+ curl_global_cleanup();
+ erofs_global_curl_initialized = false;
+ }
+#endif
+#ifdef S3EROFS_ENABLED
+ xmlCleanupParser();
+#endif
+ erofs_exit_configure();
+ erofs_mutex_unlock(&erofs_global_mutex);
+}
diff --git a/lib/liberofs_s3.h b/lib/liberofs_s3.h
index 27b041c..a178c64 100644
--- a/lib/liberofs_s3.h
+++ b/lib/liberofs_s3.h
@@ -25,6 +25,7 @@ enum s3erofs_signature_version {
#define S3_SECRET_KEY_LEN 256
struct erofs_s3 {
+ void *easy_curl;
const char *endpoint;
char access_key[S3_ACCESS_KEY_LEN + 1];
char secret_key[S3_SECRET_KEY_LEN + 1];
diff --git a/lib/remotes/s3.c b/lib/remotes/s3.c
index 1497b54..f4a364d 100644
--- a/lib/remotes/s3.c
+++ b/lib/remotes/s3.c
@@ -26,8 +26,6 @@
#define BASE64_ENCODE_LEN(len) (((len + 2) / 3) * 4)
-static CURL *easy_curl;
-
struct s3erofs_query_params {
int num;
const char *key[S3EROFS_MAX_QUERY_PARAMS];
@@ -213,6 +211,7 @@ static int s3erofs_request_perform(struct erofs_s3 *s3,
struct s3erofs_curl_request *req, void *resp)
{
struct curl_slist *request_headers = NULL;
+ CURL *curl = s3->easy_curl;
long http_code = 0;
int ret;
@@ -226,11 +225,11 @@ static int s3erofs_request_perform(struct erofs_s3 *s3,
}
}
- curl_easy_setopt(easy_curl, CURLOPT_URL, req->url);
- curl_easy_setopt(easy_curl, CURLOPT_WRITEDATA, resp);
- curl_easy_setopt(easy_curl, CURLOPT_HTTPHEADER, request_headers);
+ curl_easy_setopt(curl, CURLOPT_URL, req->url);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, resp);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, request_headers);
- ret = curl_easy_perform(easy_curl);
+ ret = curl_easy_perform(curl);
if (ret != CURLE_OK) {
erofs_err("curl_easy_perform() failed: %s",
curl_easy_strerror(ret));
@@ -238,7 +237,7 @@ static int s3erofs_request_perform(struct erofs_s3 *s3,
goto err_header;
}
- ret = curl_easy_getinfo(easy_curl, CURLINFO_RESPONSE_CODE, &http_code);
+ ret = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (ret != CURLE_OK) {
erofs_err("curl_easy_getinfo() failed: %s",
curl_easy_strerror(ret));
@@ -473,7 +472,7 @@ static int s3erofs_list_objects(struct s3erofs_object_iterator *it)
if (ret < 0)
return ret;
- if (curl_easy_setopt(easy_curl, CURLOPT_WRITEFUNCTION,
+ if (curl_easy_setopt(s3->easy_curl, CURLOPT_WRITEFUNCTION,
s3erofs_request_write_memory_cb) != CURLE_OK)
return -EIO;
@@ -547,43 +546,37 @@ s3erofs_get_next_object(struct s3erofs_object_iterator *it)
return NULL;
}
-static int s3erofs_global_init(void)
+static int s3erofs_curl_easy_init(struct erofs_s3 *s3)
{
- if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
- return -EIO;
+ CURL *curl;
- easy_curl = curl_easy_init();
- if (!easy_curl)
- goto out_err;
+ curl = curl_easy_init();
+ if (!curl)
+ return -ENOMEM;
- if (curl_easy_setopt(easy_curl, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK)
- goto out_err;
+ if (curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK)
+ goto out_cleanup;
- if (curl_easy_setopt(easy_curl, CURLOPT_CONNECTTIMEOUT, 30L) != CURLE_OK)
- goto out_err;
+ if (curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L) != CURLE_OK)
+ goto out_cleanup;
- if (curl_easy_setopt(easy_curl, CURLOPT_USERAGENT,
+ if (curl_easy_setopt(curl, CURLOPT_USERAGENT,
"s3erofs/" PACKAGE_VERSION) != CURLE_OK)
- goto out_err;
+ goto out_cleanup;
- xmlInitParser();
+ s3->easy_curl = curl;
return 0;
-out_err:
- curl_global_cleanup();
- return -EIO;
+out_cleanup:
+ curl_easy_cleanup(curl);
+ return -EFAULT;
}
-static void s3erofs_global_exit(void)
+static void s3erofs_curl_easy_exit(struct erofs_s3 *s3)
{
- if (!easy_curl)
+ if (!s3->easy_curl)
return;
-
- xmlCleanupParser();
-
- curl_easy_cleanup(easy_curl);
- easy_curl = NULL;
-
- curl_global_cleanup();
+ curl_easy_cleanup(s3->easy_curl);
+ s3->easy_curl = NULL;
}
struct s3erofs_curl_getobject_resp {
@@ -623,7 +616,7 @@ static int s3erofs_remote_getobject(struct erofs_s3 *s3,
if (ret < 0)
return ret;
- if (curl_easy_setopt(easy_curl, CURLOPT_WRITEFUNCTION,
+ if (curl_easy_setopt(s3->easy_curl, CURLOPT_WRITEFUNCTION,
s3erofs_remote_getobject_cb) != CURLE_OK)
return -EIO;
@@ -689,7 +682,7 @@ int s3erofs_build_trees(struct erofs_inode *root, struct erofs_s3 *s3,
st.st_uid = root->i_uid;
st.st_gid = root->i_gid;
- ret = s3erofs_global_init();
+ ret = s3erofs_curl_easy_init(s3);
if (ret) {
erofs_err("failed to initialize s3erofs: %s", erofs_strerror(ret));
return ret;
@@ -764,6 +757,6 @@ int s3erofs_build_trees(struct erofs_inode *root, struct erofs_s3 *s3,
err_iter:
s3erofs_destroy_object_iterator(iter);
err_global:
- s3erofs_global_exit();
+ s3erofs_curl_easy_exit(s3);
return ret;
}
diff --git a/mkfs/main.c b/mkfs/main.c
index 804d483..b8773fd 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1481,10 +1481,12 @@ int main(int argc, char **argv)
struct timeval t;
FILE *blklst = NULL;
s64 mkfs_time = 0;
- int err = 0;
+ int err;
u32 crc;
- erofs_init_configure();
+ err = liberofs_global_init();
+ if (err)
+ return 1;
erofs_mkfs_default_options();
err = mkfs_parse_options_cfg(argc, argv);
@@ -1492,13 +1494,13 @@ int main(int argc, char **argv)
if (err) {
if (err == -EINVAL)
fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
- return 1;
+ goto exit;
}
err = parse_source_date_epoch();
if (err) {
fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
- return 1;
+ goto exit;
}
g_sbi.fixed_nsec = 0;
@@ -1521,14 +1523,14 @@ int main(int argc, char **argv)
(incremental_mode ? 0 : O_TRUNC));
if (err) {
fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
- return 1;
+ goto exit;
}
#ifdef WITH_ANDROID
if (cfg.fs_config_file &&
load_canned_fs_config(cfg.fs_config_file) < 0) {
erofs_err("failed to load fs config %s", cfg.fs_config_file);
- return 1;
+ goto exit;
}
#endif
erofs_show_config();
@@ -1540,7 +1542,7 @@ int main(int argc, char **argv)
if (err) {
erofs_err("failed to initialize packedfile: %s",
strerror(-err));
- return 1;
+ goto exit;
}
}
@@ -1549,7 +1551,7 @@ int main(int argc, char **argv)
if (err) {
erofs_err("failed to initialize metabox: %s",
erofs_strerror(err));
- return 1;
+ goto exit;
}
}
@@ -1687,7 +1689,7 @@ int main(int argc, char **argv)
if (cfg.c_chunkbits) {
err = erofs_blob_init(cfg.c_blobdev_path, 1 << cfg.c_chunkbits);
if (err)
- return 1;
+ goto exit;
}
if (tar_index_512b || cfg.c_blobdev_path) {
@@ -1851,7 +1853,6 @@ exit:
erofs_xattr_cleanup_name_prefixes();
erofs_rebuild_cleanup();
erofs_diskbuf_exit();
- erofs_exit_configure();
if (source_mode == EROFS_MKFS_SOURCE_TAR) {
erofs_iostream_close(&erofstar.ios);
if (erofstar.ios.dumpfd >= 0)
@@ -1866,5 +1867,6 @@ exit:
erofs_update_progressinfo("Build completed.\n");
erofs_mkfs_showsummaries();
erofs_put_super(&g_sbi);
+ liberofs_global_exit();
return 0;
}
--
2.43.5
More information about the Linux-erofs
mailing list