diff options
author | Bernd Schubert <bschubert@ddn.com> | 2022-04-08 22:30:27 +0200 |
---|---|---|
committer | Nikolaus Rath <Nikolaus@rath.org> | 2022-09-04 13:07:15 +0100 |
commit | 30a126c5f9009e8ff8e369c563eb941679bec252 (patch) | |
tree | aa27206391ed90acf95a9339b13f1c4202c63105 /lib/fuse_loop_mt.c | |
parent | 7657ec158becdc59656c59dff40346fefde78cb2 (diff) | |
download | libfuse-30a126c5f9009e8ff8e369c563eb941679bec252.tar.gz |
API update for fuse_loop_config additions
struct fuse_loop_config was passed as a plain struct, without any
version identifer. This had two implications
1) Any addition of new parameters required a FUSE_SYMVER for
fuse_session_loop_mt() and fuse_loop_mt() as otherwise a read
beyond end-of previous struct size might have happened.
2) Filesystems also might have been recompiled and the developer
might not have noticed the struct extensions and unexpected for
the developer (or people recomliling the code) uninitialized
parameters would have been passed.
Code is updated to have struct fuse_loop_config as an opaque/private
data type for file systems that want version 312
(FUSE_MAKE_VERSION(3, 12)). The deprecated fuse_loop_config_v1
is visible, but should not be used outside of internal
conversion functions
File systems that want version >= 32 < 312 get the previous
struct (through ifdefs) and the #define of fuse_loop_mt
and fuse_session_loop_mt ensures that these recompiled file
systems call into the previous API, which then converts
the struct. This is similar to existing compiled applications
when just libfuse updated, but binaries it is solved with
the FUSE_SYMVER ABI compact declarations.
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
Diffstat (limited to 'lib/fuse_loop_mt.c')
-rw-r--r-- | lib/fuse_loop_mt.c | 93 |
1 files changed, 86 insertions, 7 deletions
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; +} + |