summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fuse.h3
-rw-r--r--include/fuse_common.h45
-rw-r--r--include/fuse_lowlevel.h41
-rw-r--r--lib/cuse_lowlevel.c7
-rw-r--r--lib/fuse.c40
-rw-r--r--lib/fuse_i.h56
-rw-r--r--lib/fuse_loop_mt.c93
-rw-r--r--lib/fuse_misc.h3
-rw-r--r--lib/fuse_versionscript14
-rw-r--r--lib/helper.c18
-rw-r--r--lib/meson.build2
-rw-r--r--meson.build2
-rw-r--r--util/meson.build2
13 files changed, 278 insertions, 48 deletions
diff --git a/include/fuse.h b/include/fuse.h
index 1a2f841..917a91c 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -1011,6 +1011,9 @@ void fuse_exit(struct fuse *f);
#if FUSE_USE_VERSION < 32
int fuse_loop_mt_31(struct fuse *f, int clone_fd);
#define fuse_loop_mt(f, clone_fd) fuse_loop_mt_31(f, clone_fd)
+#elif FUSE_USE_VERSION < FUSE_MAKE_VERSION(3, 12)
+int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config);
+#define fuse_loop_mt(f, config) fuse_loop_mt_32(f, config)
#else
/**
* FUSE event loop with multiple threads
diff --git a/include/fuse_common.h b/include/fuse_common.h
index 3f7260c..b40814f 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -23,7 +23,7 @@
#define FUSE_MAJOR_VERSION 3
/** Minor version of FUSE library interface */
-#define FUSE_MINOR_VERSION 11
+#define FUSE_MINOR_VERSION 12
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 100 + (min))
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
@@ -104,11 +104,20 @@ struct fuse_file_info {
uint32_t poll_events;
};
+
+
/**
* Configuration parameters passed to fuse_session_loop_mt() and
* fuse_loop_mt().
+ * Deprecated and replaced by a newer private struct in FUSE API
+ * version 312 (FUSE_MAKE_VERSION(3, 12)
*/
+#if FUSE_USE_VERSION < FUSE_MAKE_VERSION(3, 12)
+struct fuse_loop_config_v1; /* forward declarition */
struct fuse_loop_config {
+#else
+struct fuse_loop_config_v1 {
+#endif
/**
* whether to use separate device fds for each thread
* (may increase performance)
@@ -128,6 +137,7 @@ struct fuse_loop_config {
unsigned int max_idle_threads;
};
+
/**************************************************************************
* Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' *
**************************************************************************/
@@ -834,6 +844,39 @@ int fuse_set_signal_handlers(struct fuse_session *se);
*/
void fuse_remove_signal_handlers(struct fuse_session *se);
+/**
+ * Create and set default config for fuse_session_loop_mt and fuse_loop_mt.
+ *
+ * @return anonymous config struct
+ */
+struct fuse_loop_config *fuse_loop_cfg_create(void);
+
+/**
+ * Free the config data structure
+ */
+void fuse_loop_cfg_destroy(struct fuse_loop_config *config);
+
+/**
+ * fuse_loop_config2 setter to set the number of max idle threads.
+ */
+void fuse_loop_cfg_set_idle_threads(struct fuse_loop_config *config,
+ unsigned int value);
+
+/**
+ * fuse_loop_config2 setter to enable the clone_fd feature
+ */
+void fuse_loop_cfg_set_clone_fd(struct fuse_loop_config *config,
+ unsigned int value);
+
+/**
+ * Convert old config to more recernt fuse_loop_config2
+ *
+ * @param config current config2 type
+ * @param v1_conf older config1 type (below FUSE API 312)
+ */
+void fuse_loop_cfg_convert(struct fuse_loop_config *config,
+ struct fuse_loop_config_v1 *v1_conf);
+
/* ----------------------------------------------------------- *
* Compatibility stuff *
* ----------------------------------------------------------- */
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index d73e9fa..378742d 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -1968,26 +1968,29 @@ int fuse_session_mount(struct fuse_session *se, const char *mountpoint);
int fuse_session_loop(struct fuse_session *se);
#if FUSE_USE_VERSION < 32
-int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
-#define fuse_session_loop_mt(se, clone_fd) fuse_session_loop_mt_31(se, clone_fd)
+ int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
+ #define fuse_session_loop_mt(se, clone_fd) fuse_session_loop_mt_31(se, clone_fd)
+#elif FUSE_USE_VERSION < FUSE_MAKE_VERSION(3, 12)
+ int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config);
+ #define fuse_session_loop_mt(se, config) fuse_session_loop_mt_32(se, config)
#else
-#if (!defined(__UCLIBC__) && !defined(__APPLE__))
-/**
- * Enter a multi-threaded event loop.
- *
- * For a description of the return value and the conditions when the
- * event loop exits, refer to the documentation of
- * fuse_session_loop().
- *
- * @param se the session
- * @param config session loop configuration
- * @return see fuse_session_loop()
- */
-int fuse_session_loop_mt(struct fuse_session *se, struct fuse_loop_config *config);
-#else
-int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config);
-#define fuse_session_loop_mt(se, config) fuse_session_loop_mt_32(se, config)
-#endif
+ #if (!defined(__UCLIBC__) && !defined(__APPLE__))
+ /**
+ * Enter a multi-threaded event loop.
+ *
+ * For a description of the return value and the conditions when the
+ * event loop exits, refer to the documentation of
+ * fuse_session_loop().
+ *
+ * @param se the session
+ * @param config session loop configuration
+ * @return see fuse_session_loop()
+ */
+ int fuse_session_loop_mt(struct fuse_session *se, struct fuse_loop_config *config);
+ #else
+ int fuse_session_loop_mt_312(struct fuse_session *se, struct fuse_loop_config *config);
+ #define fuse_session_loop_mt(se, config) fuse_session_loop_mt_312(se, config)
+ #endif
#endif
/**
diff --git a/lib/cuse_lowlevel.c b/lib/cuse_lowlevel.c
index b70947e..01a62ab 100644
--- a/lib/cuse_lowlevel.c
+++ b/lib/cuse_lowlevel.c
@@ -351,10 +351,9 @@ int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci,
return 1;
if (multithreaded) {
- struct fuse_loop_config config;
- config.clone_fd = 0;
- config.max_idle_threads = 10;
- res = fuse_session_loop_mt_32(se, &config);
+ struct fuse_loop_config *config = fuse_loop_cfg_create();
+ res = fuse_session_loop_mt(se, config);
+ fuse_loop_cfg_destroy(config);
}
else
res = fuse_session_loop(se);
diff --git a/lib/fuse.c b/lib/fuse.c
index 1924caa..17850e3 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -4577,8 +4577,8 @@ int fuse_loop(struct fuse *f)
return fuse_session_loop(f->se);
}
-FUSE_SYMVER("fuse_loop_mt_32", "fuse_loop_mt@@FUSE_3.2")
-int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config)
+FUSE_SYMVER("fuse_loop_mt_312", "fuse_loop_mt@@FUSE_3.12")
+int fuse_loop_mt_312(struct fuse *f, struct fuse_loop_config *config)
{
if (f == NULL)
return -1;
@@ -4587,19 +4587,45 @@ int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config)
if (res)
return -1;
- res = fuse_session_loop_mt_32(fuse_get_session(f), config);
+ res = fuse_session_loop_mt_312(fuse_get_session(f), config);
fuse_stop_cleanup_thread(f);
return res;
}
+int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config_v1 *config_v1);
+FUSE_SYMVER("fuse_loop_mt_32", "fuse_loop_mt@FUSE_3.2")
+int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config_v1 *config_v1)
+{
+ struct fuse_loop_config *config = fuse_loop_cfg_create();
+ if (config == NULL)
+ return ENOMEM;
+
+ fuse_loop_cfg_convert(config, config_v1);
+
+ int res = fuse_loop_mt_312(f, config);
+
+ fuse_loop_cfg_destroy(config);
+
+ return res;
+}
+
int fuse_loop_mt_31(struct fuse *f, int clone_fd);
FUSE_SYMVER("fuse_loop_mt_31", "fuse_loop_mt@FUSE_3.0")
int fuse_loop_mt_31(struct fuse *f, int clone_fd)
{
- struct fuse_loop_config config;
- config.clone_fd = clone_fd;
- config.max_idle_threads = 10;
- return fuse_loop_mt_32(f, &config);
+ int err;
+ struct fuse_loop_config *config = fuse_loop_cfg_create();
+
+ if (config == NULL)
+ return ENOMEM;
+
+ fuse_loop_cfg_set_clone_fd(config, clone_fd);
+
+ err = fuse_loop_mt_312(f, config);
+
+ fuse_loop_cfg_destroy(config);
+
+ return err;
}
void fuse_exit(struct fuse *f)
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index d38b630..6930a20 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -87,6 +87,50 @@ struct fuse_module {
int ctr;
};
+/**
+ * Configuration parameters passed to fuse_session_loop_mt() and
+ * fuse_loop_mt().
+ *
+ * Internal API to avoid exposing the plain data structure and
+ * causing compat issues after adding or removing struct members.
+ *
+ */
+#if FUSE_USE_VERSION >= FUSE_MAKE_VERSION(3, 12)
+struct fuse_loop_config
+{
+ /* verififier that a correct struct was was passed. This is especially
+ * needed, as versions below (3, 12) were using a public struct
+ * (now called fuse_loop_config_v1), which was hard to extend with
+ * additional parameters, without risking that file system implementations
+ * would not have noticed and might either pass uninitialized members
+ * or even too small structs.
+ * fuse_loop_config_v1 has clone_fd at this offset, which should be either 0
+ * or 1. v2 or even higher version just need to set a value here
+ * which not conflicting and very unlikely as having been set by
+ * file system implementation.
+ */
+ int version_id;
+
+ /**
+ * whether to use separate device fds for each thread
+ * (may increase performance)
+ */
+ int clone_fd;
+ /**
+ * The maximum number of available worker threads before they
+ * start to get deleted when they become idle. If not
+ * specified, the default is 10.
+ *
+ * Adjusting this has performance implications; a very small number
+ * of threads in the pool will cause a lot of thread creation and
+ * deletion overhead and performance may suffer. When set to 0, a new
+ * thread will be created to service every operation.
+ * The special value of -1 means that this parameter is disabled.
+ */
+ int max_idle_threads;
+};
+#endif
+
/* ----------------------------------------------------------- *
* Channel interface (when using -o clone_fd) *
* ----------------------------------------------------------- */
@@ -128,8 +172,16 @@ void fuse_session_process_buf_int(struct fuse_session *se,
struct fuse *fuse_new_31(struct fuse_args *args, const struct fuse_operations *op,
size_t op_size, void *private_data);
-int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config);
-int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config);
+int fuse_loop_mt_312(struct fuse *f, struct fuse_loop_config *config);
+int fuse_session_loop_mt_312(struct fuse_session *se, struct fuse_loop_config *config);
+
+/**
+ * Internal verifier for the given config.
+ *
+ * @return negative standard error code or 0 on success
+ */
+int fuse_loop_cfg_verify(struct fuse_loop_config *config);
+
#define FUSE_MAX_MAX_PAGES 256
#define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32
diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c
index 8fcc46c..2f0470b 100644
--- a/lib/fuse_loop_mt.c
+++ b/lib/fuse_loop_mt.c
@@ -24,10 +24,16 @@
#include <sys/time.h>
#include <sys/ioctl.h>
#include <assert.h>
+#include <limits.h>
/* Environment var controlling the thread stack size */
#define ENVNAME_THREAD_STACK "FUSE_THREAD_STACK"
+#define FUSE_LOOP_MT_V2_IDENTIFIER INT_MAX - 2
+#define FUSE_LOOP_MT_DEF_CLONE_FD 0
+#define FUSE_LOOP_MT_DEF_IDLE_THREADS -1 /* thread destruction is disabled
+ * by default */
+
struct fuse_worker {
struct fuse_worker *prev;
struct fuse_worker *next;
@@ -303,13 +309,18 @@ static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w)
free(w);
}
-FUSE_SYMVER("fuse_session_loop_mt_32", "fuse_session_loop_mt@@FUSE_3.2")
-int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config)
+int fuse_session_loop_mt_312(struct fuse_session *se, struct fuse_loop_config *config);
+FUSE_SYMVER("fuse_session_loop_mt_312", "fuse_session_loop_mt@@FUSE_3.12")
+int fuse_session_loop_mt_312(struct fuse_session *se, struct fuse_loop_config *config)
{
- int err;
+int err;
struct fuse_mt mt;
struct fuse_worker *w;
+ err = fuse_loop_cfg_verify(config);
+ if (err)
+ return err;
+
memset(&mt, 0, sizeof(struct fuse_mt));
mt.se = se;
mt.clone_fd = config->clone_fd;
@@ -347,15 +358,83 @@ int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *co
if(se->error != 0)
err = se->error;
fuse_session_reset(se);
+
+ return err;
+}
+
+int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config_v1 *config_v1);
+FUSE_SYMVER("fuse_session_loop_mt_32", "fuse_session_loop_mt@FUSE_3.2")
+int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config_v1 *config_v1)
+{
+ int err;
+
+ struct fuse_loop_config *config = fuse_loop_cfg_create();
+ if (config == NULL)
+ return ENOMEM;
+
+ fuse_loop_cfg_convert(config, config_v1);
+
+ err = fuse_session_loop_mt_312(se, config);
+
+ fuse_loop_cfg_destroy(config);
+
return err;
}
+
int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
FUSE_SYMVER("fuse_session_loop_mt_31", "fuse_session_loop_mt@FUSE_3.0")
int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd)
{
- struct fuse_loop_config config;
- config.clone_fd = clone_fd;
- config.max_idle_threads = 10;
- return fuse_session_loop_mt_32(se, &config);
+ struct fuse_loop_config *config = fuse_loop_cfg_create();
+ if (clone_fd > 0)
+ fuse_loop_cfg_set_clone_fd(config, clone_fd);
+ return fuse_session_loop_mt_312(se, config);
+}
+
+struct fuse_loop_config *fuse_loop_cfg_create(void)
+{
+ struct fuse_loop_config *config = calloc(1, sizeof(*config));
+ if (config == NULL)
+ return NULL;
+
+ config->version_id = FUSE_LOOP_MT_V2_IDENTIFIER;
+ config->max_idle_threads = FUSE_LOOP_MT_DEF_IDLE_THREADS;
+ config->clone_fd = FUSE_LOOP_MT_DEF_CLONE_FD;
+
+ return config;
+}
+
+void fuse_loop_cfg_destroy(struct fuse_loop_config *config)
+{
+ free(config);
+}
+
+int fuse_loop_cfg_verify(struct fuse_loop_config *config)
+{
+ if (config->version_id != FUSE_LOOP_MT_V2_IDENTIFIER)
+ return -EINVAL;
+
+ return 0;
+}
+
+void fuse_loop_cfg_convert(struct fuse_loop_config *config,
+ struct fuse_loop_config_v1 *v1_conf)
+{
+ fuse_loop_cfg_set_idle_threads(config, v1_conf->max_idle_threads);
+
+ fuse_loop_cfg_set_clone_fd(config, v1_conf->clone_fd);
+}
+
+void fuse_loop_cfg_set_idle_threads(struct fuse_loop_config *config,
+ unsigned int value)
+{
+ config->max_idle_threads = value;
}
+
+void fuse_loop_cfg_set_clone_fd(struct fuse_loop_config *config,
+ unsigned int value)
+{
+ config->clone_fd = value;
+}
+
diff --git a/lib/fuse_misc.h b/lib/fuse_misc.h
index f956ab7..e2e9ba5 100644
--- a/lib/fuse_misc.h
+++ b/lib/fuse_misc.h
@@ -11,6 +11,9 @@
/*
Versioned symbols cannot be used in some cases because it
- not supported on MacOSX (in MachO binary format)
+
+ Note: "@@" denotes the default symbol, "@" is binary a compat version.
+
*/
#ifndef __APPLE__
# if HAVE_SYMVER_ATTRIBUTE
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index a06f768..aff7e84 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -168,6 +168,20 @@ FUSE_3.7 {
fuse_log;
} FUSE_3.4;
+FUSE_3.12 {
+ global:
+ fuse_session_loop_mt;
+ fuse_session_loop_mt_312;
+ fuse_loop_mt;
+ fuse_loop_mt_32;
+ fuse_loop_mt_312;
+ fuse_loop_cfg_create;
+ fuse_loop_cfg_destroy;
+ fuse_loop_cfg_set_idle_threads;
+ fuse_loop_cfg_set_clone_fd;
+ fuse_loop_cfg_convert;
+} FUSE_3.4;
+
# Local Variables:
# indent-tabs-mode: t
# End:
diff --git a/lib/helper.c b/lib/helper.c
index 64ff7ad..fc6a6ee 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -283,6 +283,7 @@ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
struct fuse *fuse;
struct fuse_cmdline_opts opts;
int res;
+ struct fuse_loop_config *loop_config = NULL;
if (fuse_parse_cmdline(&args, &opts) != 0)
return 1;
@@ -338,13 +339,19 @@ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
if (opts.singlethread)
res = fuse_loop(fuse);
else {
- struct fuse_loop_config loop_config;
- loop_config.clone_fd = opts.clone_fd;
- loop_config.max_idle_threads = opts.max_idle_threads;
- res = fuse_loop_mt_32(fuse, &loop_config);
+ loop_config = fuse_loop_cfg_create();
+ if (loop_config == NULL) {
+ res = 7;
+ goto out3;
+ }
+
+ fuse_loop_cfg_set_clone_fd(loop_config, opts.clone_fd);
+
+ fuse_loop_cfg_set_idle_threads(loop_config, opts.max_idle_threads);
+ res = fuse_loop_mt(fuse, loop_config);
}
if (res)
- res = 7;
+ res = 8;
fuse_remove_signal_handlers(se);
out3:
@@ -352,6 +359,7 @@ out3:
out2:
fuse_destroy(fuse);
out1:
+ fuse_loop_cfg_destroy(loop_config);
free(opts.mountpoint);
fuse_opt_free_args(&args);
return res;
diff --git a/lib/meson.build b/lib/meson.build
index 98461d8..ef0e11e 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -37,7 +37,7 @@ libfuse = library('fuse3', libfuse_sources, version: meson.project_version(),
soversion: '3', include_directories: include_dirs,
dependencies: deps, install: true,
link_depends: 'fuse_versionscript',
- c_args: [ '-DFUSE_USE_VERSION=35',
+ c_args: [ '-DFUSE_USE_VERSION=312',
'-DFUSERMOUNT_DIR="@0@"'.format(fusermount_path) ],
link_args: ['-Wl,--version-script,' + meson.current_source_dir()
+ '/fuse_versionscript' ])
diff --git a/meson.build b/meson.build
index 342dee1..3cef64f 100644
--- a/meson.build
+++ b/meson.build
@@ -1,4 +1,4 @@
-project('libfuse3', ['c'], version: '3.11.0',
+project('libfuse3', ['c'], version: '3.12.0',
meson_version: '>= 0.42',
default_options: [
'buildtype=debugoptimized',
diff --git a/util/meson.build b/util/meson.build
index 577668f..7846870 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -11,7 +11,7 @@ executable('mount.fuse3', ['mount.fuse.c'],
link_with: [ libfuse ],
install: true,
install_dir: get_option('sbindir'),
- c_args: '-DFUSE_USE_VERSION=35')
+ c_args: '-DFUSE_USE_VERSION=312')
udevrulesdir = get_option('udevrulesdir')