Skip to content

Commit

Permalink
Add idle_threads mount option.
Browse files Browse the repository at this point in the history
  • Loading branch information
joe0184 authored and Nikratio committed Aug 24, 2017
1 parent fc83143 commit f12d968
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 21 deletions.
7 changes: 7 additions & 0 deletions ChangeLog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ libfuse 3.1.1 (2017-08-06)

* Fixed a test failure when /tmp is on btrfs.

* The maximum number of idle worker threads used by `fuse_loop_mt()`
is now configurable.

* `fuse_loop_mt()` and `fuse_session_loop_mt()` now take a
`struct fuse_loop_config` parameter that supersedes the *clone_fd*
parameter.

* Incorporated several patches from the FreeBSD port. libfuse should
now compile under FreeBSD without the need for patches.

Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
AC_INIT(fuse, 3.1.1)
AC_INIT(fuse, 3.2.0)
AC_PREREQ(2.59d)
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_TARGET
Expand Down
10 changes: 7 additions & 3 deletions include/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -964,13 +964,17 @@ void fuse_exit(struct fuse *f);
* in the callback function of fuse_operations is also thread-safe.
*
* @param f the FUSE handle
* @param clone_fd whether to use separate device fds for each thread
* (may increase performance)
* @param config loop configuration
* @return see fuse_session_loop()
*
* See also: fuse_loop()
*/
int fuse_loop_mt(struct fuse *f, int clone_fd);
#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)
#else
int fuse_loop_mt(struct fuse *f, struct fuse_loop_config *config);
#endif

/**
* Get the current context
Expand Down
24 changes: 23 additions & 1 deletion include/fuse_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#define FUSE_MAJOR_VERSION 3

/** Minor version of FUSE library interface */
#define FUSE_MINOR_VERSION 1
#define FUSE_MINOR_VERSION 2

#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
Expand Down Expand Up @@ -79,7 +79,29 @@ struct fuse_file_info {
uint32_t poll_events;
};

/**
* Configuration parameters passed to fuse_session_loop_mt() and
* fuse_loop_mt().
*/
struct fuse_loop_config {
/**
* 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.
*/
unsigned int max_idle_threads;
};

/**************************************************************************
* Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' *
Expand Down
11 changes: 8 additions & 3 deletions include/fuse_lowlevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -1760,6 +1760,7 @@ struct fuse_cmdline_opts {
int show_version;
int show_help;
int clone_fd;
unsigned int max_idle_threads;
};

/**
Expand Down Expand Up @@ -1857,11 +1858,15 @@ int fuse_session_loop(struct fuse_session *se);
* fuse_session_loop().
*
* @param se the session
* @param clone_fd whether to use separate device fds for each thread
* (may increase performance)
* @param config session loop configuration
* @return see fuse_session_loop()
*/
int fuse_session_loop_mt(struct fuse_session *se, int clone_fd);
#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)
#else
int fuse_session_loop_mt(struct fuse_session *se, struct fuse_loop_config *config);
#endif

/**
* Flag a session as terminated.
Expand Down
2 changes: 1 addition & 1 deletion lib/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Process this file with automake to produce Makefile.in

AM_CPPFLAGS = -I$(top_srcdir)/include -DFUSERMOUNT_DIR=\"$(bindir)\" \
-D_REENTRANT -DFUSE_USE_VERSION=31
-D_REENTRANT -DFUSE_USE_VERSION=32

lib_LTLIBRARIES = libfuse3.la

Expand Down
8 changes: 6 additions & 2 deletions lib/cuse_lowlevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,12 @@ int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci,
if (se == NULL)
return 1;

if (multithreaded)
res = fuse_session_loop_mt(se, 0);
if (multithreaded) {
struct fuse_loop_config config;
config.clone_fd = 0;
config.max_idle_threads = 10;
res = fuse_session_loop_mt(se, &config);
}
else
res = fuse_session_loop(se);

Expand Down
16 changes: 14 additions & 2 deletions lib/fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -4382,7 +4382,9 @@ int fuse_loop(struct fuse *f)
return fuse_session_loop(f->se);
}

int fuse_loop_mt(struct fuse *f, int clone_fd)
int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config);
FUSE_SYMVER(".symver fuse_loop_mt_32,fuse_loop_mt@@FUSE_3.2");
int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config)
{
if (f == NULL)
return -1;
Expand All @@ -4391,11 +4393,21 @@ int fuse_loop_mt(struct fuse *f, int clone_fd)
if (res)
return -1;

res = fuse_session_loop_mt(fuse_get_session(f), clone_fd);
res = fuse_session_loop_mt(fuse_get_session(f), config);
fuse_stop_cleanup_thread(f);
return res;
}

int fuse_loop_mt_31(struct fuse *f, int clone_fd);
FUSE_SYMVER(".symver fuse_loop_mt_31,fuse_loop_mt@FUSE_3.1");
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);
}

void fuse_exit(struct fuse *f)
{
fuse_session_exit(f->se);
Expand Down
20 changes: 17 additions & 3 deletions lib/fuse_loop_mt.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct fuse_mt {
int exit;
int error;
int clone_fd;
int max_idle;
};

static struct fuse_chan *fuse_chan_new(int fd)
Expand Down Expand Up @@ -161,7 +162,7 @@ static void *fuse_do_work(void *data)
pthread_mutex_lock(&mt->lock);
if (!isforget)
mt->numavail++;
if (mt->numavail > 10) {
if (mt->numavail > mt->max_idle) {
if (mt->exit) {
pthread_mutex_unlock(&mt->lock);
return NULL;
Expand Down Expand Up @@ -300,18 +301,21 @@ static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w)
free(w);
}

int fuse_session_loop_mt(struct fuse_session *se, int clone_fd)
int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config);
FUSE_SYMVER(".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 err;
struct fuse_mt mt;
struct fuse_worker *w;

memset(&mt, 0, sizeof(struct fuse_mt));
mt.se = se;
mt.clone_fd = clone_fd;
mt.clone_fd = config->clone_fd;
mt.error = 0;
mt.numworker = 0;
mt.numavail = 0;
mt.max_idle = config->max_idle_threads;
mt.main.thread_id = pthread_self();
mt.main.prev = mt.main.next = &mt.main;
sem_init(&mt.finish, 0, 0);
Expand Down Expand Up @@ -344,3 +348,13 @@ int fuse_session_loop_mt(struct fuse_session *se, int clone_fd)
fuse_session_reset(se);
return err;
}

int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
FUSE_SYMVER(".symver fuse_session_loop_mt_31,fuse_session_loop_mt@FUSE_3.1");
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);
}
6 changes: 6 additions & 0 deletions lib/fuse_versionscript
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ FUSE_3.1 {
fuse_invalidate_path;
} FUSE_3.0;

FUSE_3.2 {
global:
fuse_session_loop_mt_31;
fuse_loop_mt_31;
} FUSE_3.1;

# Local Variables:
# indent-tabs-mode: t
# End:
16 changes: 13 additions & 3 deletions lib/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ static const struct fuse_opt fuse_helper_opts[] = {
FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP),
#endif
FUSE_HELPER_OPT("clone_fd", clone_fd),
FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
FUSE_OPT_END
};

Expand Down Expand Up @@ -132,7 +133,9 @@ void fuse_cmdline_help(void)
" -f foreground operation\n"
" -s disable multi-threaded operation\n"
" -o clone_fd use separate fuse device fd for each thread\n"
" (may improve performance)\n");
" (may improve performance)\n"
" -o max_idle_threads the maximum number of idle worker threads\n"
" allowed (default: 10)\n");
}

static int fuse_helper_opt_proc(void *data, const char *arg, int key,
Expand Down Expand Up @@ -195,6 +198,9 @@ int fuse_parse_cmdline(struct fuse_args *args,
struct fuse_cmdline_opts *opts)
{
memset(opts, 0, sizeof(struct fuse_cmdline_opts));

opts->max_idle_threads = 10;

if (fuse_opt_parse(args, opts, fuse_helper_opts,
fuse_helper_opt_proc) == -1)
return -1;
Expand Down Expand Up @@ -326,8 +332,12 @@ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,

if (opts.singlethread)
res = fuse_loop(fuse);
else
res = fuse_loop_mt(fuse, opts.clone_fd);
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(fuse, &loop_config);
}
if (res)
res = 1;

Expand Down
2 changes: 1 addition & 1 deletion lib/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,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=31',
c_args: [ '-DFUSE_USE_VERSION=32',
'-DFUSERMOUNT_DIR="{}"'.format(fusermount_path) ],
link_args: ['-Wl,--version-script,' + meson.current_source_dir()
+ '/fuse_versionscript' ])
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
project('libfuse3', 'c', version: '3.1.1',
project('libfuse3', 'c', version: '3.2.0',
meson_version: '>= 0.38',
default_options: [ 'buildtype=debugoptimized' ])

Expand Down

0 comments on commit f12d968

Please sign in to comment.