From 856c683c361cb1f3a176df331cbbac76c34402e7 Mon Sep 17 00:00:00 2001 From: Bernd Schubert Date: Tue, 22 Mar 2022 19:55:36 +0100 Subject: passthrough_hp: Add options for clone_fd, max_threads, daemonize This is useful for benchmarking. Note: This changes behavior - passthrough_hp runs in background by default now. --- example/passthrough_hp.cc | 31 +++++++++++++++++++++++++++++-- lib/fuse_loop_mt.c | 9 +++++++++ test/test_examples.py | 2 ++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/example/passthrough_hp.cc b/example/passthrough_hp.cc index e86da5d..0167738 100644 --- a/example/passthrough_hp.cc +++ b/example/passthrough_hp.cc @@ -82,6 +82,9 @@ using namespace std; +#define SFS_DEFAULT_THREADS "-1" // take libfuse value as default +#define SFS_DEFAULT_CLONE_FD "0" + /* We are re-using pointers to our `struct sfs_inode` and `struct sfs_dirp` elements as inodes and file handles. This means that we must be able to store pointer a pointer in both a fuse_ino_t @@ -149,11 +152,15 @@ struct Fs { Inode root; double timeout; bool debug; + bool debug_fuse; + bool foreground; std::string source; size_t blocksize; dev_t src_dev; bool nosplice; bool nocache; + size_t num_threads; + bool clone_fd; }; static Fs fs{}; @@ -1176,10 +1183,16 @@ static cxxopts::ParseResult parse_options(int argc, char **argv) { opt_parser.add_options() ("debug", "Enable filesystem debug messages") ("debug-fuse", "Enable libfuse debug messages") + ("foreground", "Run in foreground") ("help", "Print help") ("nocache", "Disable all caching") ("nosplice", "Do not use splice(2) to transfer data") - ("single", "Run single-threaded"); + ("single", "Run single-threaded") + ("num-threads", "Number of libfuse worker threads", + cxxopts::value()->default_value(SFS_DEFAULT_THREADS)) + ("clone-fd", "use separate fuse device fd for each thread", + cxxopts::value()->implicit_value(SFS_DEFAULT_CLONE_FD)); + // FIXME: Find a better way to limit the try clause to just // opt_parser.parse() (cf. https://github.com/jarro2783/cxxopts/issues/146) @@ -1201,7 +1214,15 @@ static cxxopts::ParseResult parse_options(int argc, char **argv) { } fs.debug = options.count("debug") != 0; + fs.debug_fuse = options.count("debug-fuse") != 0; + + fs.foreground = options.count("foreground") != 0; + if (fs.debug || fs.debug_fuse) + fs.foreground = true; + fs.nosplice = options.count("nosplice") != 0; + fs.num_threads = options["num-threads"].as(); + fs.clone_fd = options["clone-fd"].as(); char* resolved_path = realpath(argv[1], NULL); if (resolved_path == NULL) warn("WARNING: realpath() failed with"); @@ -1233,6 +1254,7 @@ int main(int argc, char *argv[]) { // Parse command line options auto options {parse_options(argc, argv)}; + // We need an fd for every dentry in our the filesystem that the // kernel knows about. This is way more than most processes need, // so try to get rid of any resource softlimit. @@ -1260,7 +1282,7 @@ int main(int argc, char *argv[]) { if (fuse_opt_add_arg(&args, argv[0]) || fuse_opt_add_arg(&args, "-o") || fuse_opt_add_arg(&args, "default_permissions,fsname=hpps") || - (options.count("debug-fuse") && fuse_opt_add_arg(&args, "-odebug"))) + (fs.debug_fuse && fuse_opt_add_arg(&args, "-odebug"))) errx(3, "ERROR: Out of memory"); fuse_lowlevel_ops sfs_oper {}; @@ -1275,9 +1297,14 @@ int main(int argc, char *argv[]) { // Don't apply umask, use modes exactly as specified umask(0); + fuse_daemonize(fs.foreground); + // Mount and run main loop loop_config = fuse_loop_cfg_create(); + if (fs.num_threads != -1) + fuse_loop_cfg_set_idle_threads(loop_config, fs.num_threads); + if (fuse_session_mount(se, argv[2]) != 0) goto err_out3; if (options.count("single")) diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 72c74a8..b8b2fdd 100644 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c @@ -35,6 +35,9 @@ #define FUSE_LOOP_MT_DEF_IDLE_THREADS -1 /* thread destruction is disabled * by default */ +/* an arbitrary large value that cannot be valid */ +#define FUSE_LOOP_MT_MAX_THREADS (100U * 1000) + struct fuse_worker { struct fuse_worker *prev; struct fuse_worker *next; @@ -460,6 +463,12 @@ void fuse_loop_cfg_convert(struct fuse_loop_config *config, void fuse_loop_cfg_set_idle_threads(struct fuse_loop_config *config, unsigned int value) { + if (value > FUSE_LOOP_MT_MAX_THREADS) { + fuse_log(FUSE_LOG_ERR, + "Ignoring invalid max threads value " + "%u > max (%u).\n", value, FUSE_LOOP_MT_MAX_THREADS); + return; + } config->max_idle_threads = value; } diff --git a/test/test_examples.py b/test/test_examples.py index cfce57c..c63ac11 100755 --- a/test/test_examples.py +++ b/test/test_examples.py @@ -197,6 +197,8 @@ def test_passthrough_hp(short_tmpdir, cache, output_checker): [ pjoin(basename, 'example', 'passthrough_hp'), src_dir, mnt_dir ] + cmdline.append('--foreground') + if not cache: cmdline.append('--nocache') -- cgit v1.2.1