summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernd Schubert <bschubert@ddn.com>2022-03-22 19:55:36 +0100
committerNikolaus Rath <Nikolaus@rath.org>2023-01-13 10:21:42 +0000
commit856c683c361cb1f3a176df331cbbac76c34402e7 (patch)
tree8a1b461ff5f3eded9d0823b220e03290dc71b049
parentaad5c3a44d4386b2128b956446b2c6295a4c28ad (diff)
downloadfuse-856c683c361cb1f3a176df331cbbac76c34402e7.tar.gz
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.
-rw-r--r--example/passthrough_hp.cc31
-rw-r--r--lib/fuse_loop_mt.c9
-rwxr-xr-xtest/test_examples.py2
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<int>()->default_value(SFS_DEFAULT_THREADS))
+ ("clone-fd", "use separate fuse device fd for each thread",
+ cxxopts::value<bool>()->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<int>();
+ fs.clone_fd = options["clone-fd"].as<bool>();
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')