From d49f2e77b4741706ec125cc62ea913ed5d39bd39 Mon Sep 17 00:00:00 2001 From: Nikolaus Rath Date: Sat, 15 Oct 2016 16:09:16 -0700 Subject: [PATCH] Unify handling of fuse_conn_info options Instead of using command line options to modify struct fuse_conn_info before and after calling the init() handler, we now give the file system explicit control over this. --- ChangeLog.rst | 36 +++++---- example/hello_ll.c | 1 - example/notify_inval_entry.c | 1 - example/notify_inval_inode.c | 1 - example/notify_store_retrieve.c | 1 - example/passthrough_ll.c | 1 - include/fuse_common.h | 55 ++++++++++++++ include/fuse_lowlevel.h | 16 ++-- lib/fuse.c | 1 - lib/fuse_i.h | 23 ------ lib/fuse_lowlevel.c | 99 ------------------------- lib/helper.c | 127 ++++++++++++++++++++++++++++++++ test/test_examples.py | 15 ++-- test/test_write_cache.c | 12 ++- 14 files changed, 227 insertions(+), 162 deletions(-) diff --git a/ChangeLog.rst b/ChangeLog.rst index a498273..528efb0 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -9,22 +9,32 @@ Unreleased Changes the `splice_read` option is now enabled by default. As usual, this can be changed in the file system's `init` handler. -* `fuse_session_new` now treats low-level options more consistently: - First, options are used to modify FUSE defaults. Second, the file - system may inspect and/or adjust the settings in its `init` - handler. Third, command line arguments take precedence over any - modifications made by the `init` handler. - -* Removed the `async_read` field from `struct fuse_conn_info`. To - determine if the kernel supports asynchronous reads, file systems - should check the `FUSE_CAP_ASYNC_READ` bit of the `capable` - field. To enable/disable asynchronous reads, file systems should set - the flag in the `wanted` field. +* The treatment of low-level options has been made more consistent: + + Options that can be set in the init() handler (via the + fuse_conn_info parameter) can now be set only here, + i.e. fuse_session_new() no longer accepts arguments that change the + fuse_conn_info object before or after the call do init(). As a side + effect, this removes the ambiguity where some options can be + overwritten by init(), while others overwrite the choices made by + init(). + + For file systems that wish to offer command line options for these + settings, the new fuse_parse_conn_info_opts() and + fuse_apply_conn_info_opts() functions are available. + + Consequently, the fuse_lowlevel_help() method has been dropped. + +* The `async_read` field in `struct fuse_conn_info` has been + removed. To determine if the kernel supports asynchronous reads, + file systems should check the `FUSE_CAP_ASYNC_READ` bit of the + `capable` field. To enable/disable asynchronous reads, file systems + should set the flag in the `wanted` field. * The `fuse_parse_cmdline` function no longer prints out help when the ``--verbose`` or ``--help`` flags are given. This needs to be done - by the file system (e.g. using the `fuse_cmdline_help()`, - `fuse_lowlevel_help()` and `fuse_mount_help()` functions). + by the file system (e.g. using the `fuse_cmdline_help()` and + `fuse_mount_help()` functions). * Added ``example/cuse_client.c`` to test ``example/cuse.c``. diff --git a/example/hello_ll.c b/example/hello_ll.c index e0ce610..81d04c3 100644 --- a/example/hello_ll.c +++ b/example/hello_ll.c @@ -195,7 +195,6 @@ int main(int argc, char *argv[]) if (opts.show_help) { printf("usage: %s [options] \n\n", argv[0]); fuse_cmdline_help(); - fuse_lowlevel_help(); fuse_mount_help(); ret = 0; goto err_out1; diff --git a/example/notify_inval_entry.c b/example/notify_inval_entry.c index 1c2a6c9..bb6f2ef 100644 --- a/example/notify_inval_entry.c +++ b/example/notify_inval_entry.c @@ -287,7 +287,6 @@ int main(int argc, char *argv[]) { if (opts.show_help) { show_help(argv[0]); fuse_cmdline_help(); - fuse_lowlevel_help(); fuse_mount_help(); ret = 0; goto err_out1; diff --git a/example/notify_inval_inode.c b/example/notify_inval_inode.c index c9ab4d8..078107e 100644 --- a/example/notify_inval_inode.c +++ b/example/notify_inval_inode.c @@ -310,7 +310,6 @@ int main(int argc, char *argv[]) { if (opts.show_help) { show_help(argv[0]); fuse_cmdline_help(); - fuse_lowlevel_help(); fuse_mount_help(); ret = 0; goto err_out1; diff --git a/example/notify_store_retrieve.c b/example/notify_store_retrieve.c index 5b5fa63..8cc6666 100644 --- a/example/notify_store_retrieve.c +++ b/example/notify_store_retrieve.c @@ -353,7 +353,6 @@ int main(int argc, char *argv[]) { if (opts.show_help) { show_help(argv[0]); fuse_cmdline_help(); - fuse_lowlevel_help(); fuse_mount_help(); ret = 0; goto err_out1; diff --git a/example/passthrough_ll.c b/example/passthrough_ll.c index df9d7d3..7884242 100644 --- a/example/passthrough_ll.c +++ b/example/passthrough_ll.c @@ -469,7 +469,6 @@ int main(int argc, char *argv[]) if (opts.show_help) { printf("usage: %s [options] \n\n", argv[0]); fuse_cmdline_help(); - fuse_lowlevel_help(); fuse_mount_help(); ret = 0; goto err_out1; diff --git a/include/fuse_common.h b/include/fuse_common.h index 55f0de2..2a0db73 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -205,6 +205,61 @@ struct fuse_conn_info { struct fuse_session; struct fuse_pollhandle; +struct fuse_conn_info_opts; + +/** + * This function parses several command-line options that can be used + * to override elements of struct fuse_conn_info. The pointer returned + * by this function should be passed to the + * fuse_apply_conn_info_opts() method by the file system's init() + * handler. + * + * Before using this function, think twice if you really want these + * parameters to be adjustable from the command line. In most cases, + * they should be determined by the file system internally. + * + * The following options are recognized: + * + * -o max_write=N sets conn->max_write + * -o max_readahead=N sets conn->max_readahead + * -o max_background=N sets conn->max_background + * -o congestion_threshold=N sets conn->congestion_threshold + * -o async_read sets FUSE_CAP_ASYNC_READ in conn->want + * -o sync_read unsets FUSE_CAP_ASYNC_READ in conn->want + * -o atomic_o_trunc sets FUSE_CAP_ATOMIC_O_TRUNC in conn->want + * -o no_remote_lock Equivalent to -o no_remote_flock,no_remote_posix_lock + * -o no_remote_flock Unsets FUSE_CAP_FLOCK_LOCKS in conn->want + * -o no_remote_posix_lock Unsets FUSE_CAP_POSIX_LOCKS in conn->want + * -o [no_]splice_write (un-)sets FUSE_CAP_SPLICE_WRITE in conn->want + * -o [no_]splice_move (un-)sets FUSE_CAP_SPLICE_MOVE in conn->want + * -o [no_]splice_read (un-)sets FUSE_CAP_SPLICE_READ in conn->want + * -o [no_]auto_inval_data (un-)sets FUSE_CAP_AUTO_INVAL_DATA in conn->want + * -o readdirplus=no unsets FUSE_CAP_READDIRPLUS in conn->want + * -o readdirplus=yes sets FUSE_CAP_READDIRPLUS and unsets + * FUSE_CAP_READDIRPLUS_AUTO in conn->want + * -o readdirplus=auto sets FUSE_CAP_READDIRPLUS and + * FUSE_CAP_READDIRPLUS_AUTO in conn->want + * -o [no_]async_dio (un-)sets FUSE_CAP_ASYNC_DIO in conn->want + * -o [no_]writeback_cache (un-)sets FUSE_CAP_WRITEBACK_CACHE in conn->want + * -o time_gran=N sets conn->time_gran + * + * Known options will be removed from *args*, unknown options will be + * passed through unchanged. + * + * @param args argument vector (input+output) + * @return parsed options + **/ +struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args); + +/** + * This function applies the (parsed) parameters in *opts* to the + * *conn* pointer. It may modify the following fields: wants, + * max_write, max_readahead, congestion_threshold, max_background, + * time_gran. A field is only set (or unset) if the corresponding + * option has been explicitly set. + */ +void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts, + struct fuse_conn_info *conn); /** * Go into the background diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index 0b7ee2b..d3aa484 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -1627,19 +1627,12 @@ void fuse_lowlevel_version(void); */ void fuse_mount_version(void); -/** - * Print available low-level options to stdout. - * These options may be passed to `fuse_session_new()` - */ -void fuse_lowlevel_help(void); - /** * Print available mount options to stdout. * These options may be passed to `fuse_session_new()` */ void fuse_mount_help(void); - /** * Print available options for `fuse_parse_cmdline()`. */ @@ -1684,9 +1677,12 @@ int fuse_parse_cmdline(struct fuse_args *args, * Returns a session structure suitable for passing to * fuse_session_mount() and fuse_session_loop(). * - * Known options are defined in `struct fuse_opt fuse_ll_opts[]` and - * `struct fuse_opt fuse_mount_opts[]`. If not all options are known, - * an error message is written to stderr and the function returns NULL. + * Known options can be listed by fuse_mount_help(). Additionally, + * this function accepts the `--debug` option (which is not explicitly + * listed by fuse_mount_help()). + * + * If not all options are known, an error message is written to stderr + * and the function returns NULL. * * @param args argument vector * @param op the (low-level) filesystem operations diff --git a/lib/fuse.c b/lib/fuse.c index fb15b04..ff46f78 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -4661,7 +4661,6 @@ struct fuse *fuse_new(struct fuse_args *args, if (f->conf.show_help) { fuse_lib_help(); - fuse_lowlevel_help(); fuse_mount_help(); /* Defer printing module help until modules have been loaded */ diff --git a/lib/fuse_i.h b/lib/fuse_i.h index 5ed23c7..e612b3f 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -41,34 +41,11 @@ struct fuse_notify_req { struct fuse_notify_req *prev; }; -struct session_opts { - int atomic_o_trunc; - int no_remote_posix_lock; - int no_remote_flock; - int splice_write; - int splice_move; - int splice_read; - int no_splice_write; - int no_splice_move; - int no_splice_read; - int auto_inval_data; - int no_auto_inval_data; - int no_readdirplus; - int no_readdirplus_auto; - int async_dio; - int no_async_dio; - int writeback_cache; - int no_writeback_cache; - int async_read; - int sync_read; -}; - struct fuse_session { char *mountpoint; volatile int exited; int fd; struct mount_opts *mo; - struct session_opts opts; int debug; int allow_root; struct fuse_lowlevel_ops op; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index a96f3a5..736cec6 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -1809,42 +1809,6 @@ static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fuse_reply_err(req, ENOSYS); } -static void apply_want_options(struct session_opts *opts, - struct fuse_conn_info *conn) -{ -#define LL_ENABLE(cond,cap) \ - if (cond) conn->want |= (cap) -#define LL_DISABLE(cond,cap) \ - if (cond) conn->want &= ~(cap) - - LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ); - LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ); - - LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE); - LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE); - - LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE); - LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE); - - LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA); - LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA); - - LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS); - LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO); - - LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO); - LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO); - - LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE); - LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE); - - LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ); - LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ); - - LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS); - LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS); -} - static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) { struct fuse_init_in *arg = (struct fuse_init_in *) inarg; @@ -1949,19 +1913,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.max_write = bufsize; f->got_init = 1; - - /* Apply command-line options (so that init() handler has - an idea about user preferences */ - apply_want_options(&f->opts, &f->conn); - - /* Allow file-system to overwrite defaults */ if (f->op.init) f->op.init(f->userdata, &f->conn); - /* Now explicitly overwrite file-system's decision - with command-line options */ - apply_want_options(&f->opts, &f->conn); - /* Always enable big writes, this is superseded by the max_write option */ outarg.flags |= FUSE_BIG_WRITES; @@ -2570,35 +2524,6 @@ static const struct fuse_opt fuse_ll_opts[] = { LL_OPTION("debug", debug, 1), LL_OPTION("-d", debug, 1), LL_OPTION("allow_root", allow_root, 1), - LL_OPTION("max_write=%u", conn.max_write, 0), - LL_OPTION("max_readahead=%u", conn.max_readahead, 0), - LL_OPTION("max_background=%u", conn.max_background, 0), - LL_OPTION("congestion_threshold=%u", conn.congestion_threshold, 0), - LL_OPTION("sync_read", opts.sync_read, 1), - LL_OPTION("async_read", opts.async_read, 1), - LL_OPTION("atomic_o_trunc", opts.atomic_o_trunc, 1), - LL_OPTION("no_remote_lock", opts.no_remote_posix_lock, 1), - LL_OPTION("no_remote_lock", opts.no_remote_flock, 1), - LL_OPTION("no_remote_flock", opts.no_remote_flock, 1), - LL_OPTION("no_remote_posix_lock", opts.no_remote_posix_lock, 1), - LL_OPTION("splice_write", opts.splice_write, 1), - LL_OPTION("no_splice_write", opts.no_splice_write, 1), - LL_OPTION("splice_move", opts.splice_move, 1), - LL_OPTION("no_splice_move", opts.no_splice_move, 1), - LL_OPTION("splice_read", opts.splice_read, 1), - LL_OPTION("no_splice_read", opts.no_splice_read, 1), - LL_OPTION("auto_inval_data", opts.auto_inval_data, 1), - LL_OPTION("no_auto_inval_data", opts.no_auto_inval_data, 1), - LL_OPTION("readdirplus=no", opts.no_readdirplus, 1), - LL_OPTION("readdirplus=yes", opts.no_readdirplus, 0), - LL_OPTION("readdirplus=yes", opts.no_readdirplus_auto, 1), - LL_OPTION("readdirplus=auto", opts.no_readdirplus, 0), - LL_OPTION("readdirplus=auto", opts.no_readdirplus_auto, 0), - LL_OPTION("async_dio", opts.async_dio, 1), - LL_OPTION("no_async_dio", opts.no_async_dio, 1), - LL_OPTION("writeback_cache", opts.writeback_cache, 1), - LL_OPTION("no_writeback_cache", opts.no_writeback_cache, 1), - LL_OPTION("time_gran=%u", conn.time_gran, 0), FUSE_OPT_END }; @@ -2608,30 +2533,6 @@ void fuse_lowlevel_version(void) FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); } -void fuse_lowlevel_help(void) -{ - printf( -"Low-level options\n" -" -o max_write=N set maximum size of write requests\n" -" -o max_readahead=N set maximum readahead\n" -" -o max_background=N set number of maximum background requests\n" -" -o congestion_threshold=N set kernel's congestion threshold\n" -" -o async_read perform reads asynchronously (default)\n" -" -o sync_read perform reads synchronously\n" -" -o atomic_o_trunc enable atomic open+truncate support\n" -" -o no_remote_lock disable remote file locking\n" -" -o no_remote_flock disable remote file locking (BSD)\n" -" -o no_remote_posix_lock disable remote file locking (POSIX)\n" -" -o [no_]splice_write use splice to write to the fuse device\n" -" -o [no_]splice_move move data while splicing to the fuse device\n" -" -o [no_]splice_read use splice to read from the fuse device\n" -" -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n" -" -o readdirplus=S control readdirplus use (yes|no|auto)\n" -" -o [no_]async_dio asynchronous direct I/O\n" -" -o [no_]writeback_cache asynchronous, buffered writes\n" -" -o time_gran=N time granularity in nsec\n\n"); -} - void fuse_session_destroy(struct fuse_session *se) { struct fuse_ll_pipe *llp; diff --git a/lib/helper.c b/lib/helper.c index ea06d81..6044bb3 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -49,6 +49,69 @@ static const struct fuse_opt fuse_helper_opts[] = { FUSE_OPT_END }; +struct fuse_conn_info_opts { + int atomic_o_trunc; + int no_remote_posix_lock; + int no_remote_flock; + int splice_write; + int splice_move; + int splice_read; + int no_splice_write; + int no_splice_move; + int no_splice_read; + int auto_inval_data; + int no_auto_inval_data; + int no_readdirplus; + int no_readdirplus_auto; + int async_dio; + int no_async_dio; + int writeback_cache; + int no_writeback_cache; + int async_read; + int sync_read; + unsigned max_write; + unsigned max_readahead; + unsigned max_background; + unsigned congestion_threshold; + unsigned time_gran; +}; + +#define CONN_OPTION(t, p, v) \ + { t, offsetof(struct fuse_conn_info_opts, p), v } +static const struct fuse_opt conn_info_opt_spec[] = { + CONN_OPTION("max_write=%u", max_write, 0), + CONN_OPTION("max_readahead=%u", max_readahead, 0), + CONN_OPTION("max_background=%u", max_background, 0), + CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0), + CONN_OPTION("sync_read", sync_read, 1), + CONN_OPTION("async_read", async_read, 1), + CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1), + CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1), + CONN_OPTION("no_remote_lock", no_remote_flock, 1), + CONN_OPTION("no_remote_flock", no_remote_flock, 1), + CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1), + CONN_OPTION("splice_write", splice_write, 1), + CONN_OPTION("no_splice_write", no_splice_write, 1), + CONN_OPTION("splice_move", splice_move, 1), + CONN_OPTION("no_splice_move", no_splice_move, 1), + CONN_OPTION("splice_read", splice_read, 1), + CONN_OPTION("no_splice_read", no_splice_read, 1), + CONN_OPTION("auto_inval_data", auto_inval_data, 1), + CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1), + CONN_OPTION("readdirplus=no", no_readdirplus, 1), + CONN_OPTION("readdirplus=yes", no_readdirplus, 0), + CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1), + CONN_OPTION("readdirplus=auto", no_readdirplus, 0), + CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0), + CONN_OPTION("async_dio", async_dio, 1), + CONN_OPTION("no_async_dio", no_async_dio, 1), + CONN_OPTION("writeback_cache", writeback_cache, 1), + CONN_OPTION("no_writeback_cache", no_writeback_cache, 1), + CONN_OPTION("time_gran=%u", time_gran, 0), + FUSE_OPT_END +}; + + void fuse_cmdline_help(void) { printf("General options:\n" @@ -262,3 +325,67 @@ out1: fuse_opt_free_args(&args); return res; } + + +void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts, + struct fuse_conn_info *conn) +{ + if(opts->max_write) + conn->max_write = opts->max_write; + if(opts->max_background) + conn->max_background = opts->max_background; + if(opts->congestion_threshold) + conn->congestion_threshold = opts->congestion_threshold; + if(opts->time_gran) + conn->time_gran = opts->time_gran; + if(opts->max_readahead) + conn->max_readahead = opts->max_readahead; + +#define LL_ENABLE(cond,cap) \ + if (cond) conn->want |= (cap) +#define LL_DISABLE(cond,cap) \ + if (cond) conn->want &= ~(cap) + + LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ); + LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ); + + LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE); + LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE); + + LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE); + LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE); + + LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA); + LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA); + + LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS); + LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO); + + LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO); + LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO); + + LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE); + LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE); + + LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ); + LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ); + + LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS); + LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS); +} + +struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args) +{ + struct fuse_conn_info_opts *opts; + + opts = calloc(1, sizeof(struct fuse_conn_info_opts)); + if(opts == NULL) { + fprintf(stderr, "calloc failed\n"); + return NULL; + } + if(fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) { + free(opts); + return NULL; + } + return opts; +} diff --git a/test/test_examples.py b/test/test_examples.py index a8064c3..8868a98 100755 --- a/test/test_examples.py +++ b/test/test_examples.py @@ -29,11 +29,8 @@ def name_generator(__ctr=[0]): __ctr[0] += 1 return 'testfile_%d' % __ctr[0] -LL_OPTIONS = [ ['-o', 'splice_move,splice_write,splice_read' ], - ['-o', 'clone_fd,writeback_cache' ] ] - @pytest.mark.parametrize("name", ('hello', 'hello_ll')) -@pytest.mark.parametrize("options", LL_OPTIONS) +@pytest.mark.parametrize("options", ([], ['-o', 'clone_fd'])) def test_hello(tmpdir, name, options): mnt_dir = str(tmpdir) cmdline = base_cmdline + \ @@ -63,14 +60,13 @@ def test_hello(tmpdir, name, options): @pytest.mark.parametrize("name", ('passthrough', 'passthrough_fh', 'passthrough_ll')) -@pytest.mark.parametrize("options", LL_OPTIONS) -def test_passthrough(tmpdir, name, options): +def test_passthrough(tmpdir, name): mnt_dir = str(tmpdir.mkdir('mnt')) src_dir = str(tmpdir.mkdir('src')) cmdline = base_cmdline + \ [ pjoin(basename, 'example', name), - '-f', mnt_dir ] + options + '-f', mnt_dir ] if not name.endswith('_ll'): cmdline += [ '-o', 'use_ino,readdir_ino,kernel_cache' ] mount_process = subprocess.Popen(cmdline) @@ -146,13 +142,12 @@ def test_poll(tmpdir): @pytest.mark.parametrize("name", ('notify_inval_inode', 'notify_store_retrieve')) -@pytest.mark.parametrize("options", LL_OPTIONS) @pytest.mark.parametrize("notify", (True, False)) -def test_notify1(tmpdir, name, options, notify): +def test_notify1(tmpdir, name, notify): mnt_dir = str(tmpdir) cmdline = base_cmdline + \ [ pjoin(basename, 'example', name), - '-f', '--update-interval=1', mnt_dir ] + options + '-f', '--update-interval=1', mnt_dir ] if not notify: cmdline.append('--no-notify') mount_process = subprocess.Popen(cmdline) diff --git a/test/test_write_cache.c b/test/test_write_cache.c index d2f7004..137cb8d 100644 --- a/test/test_write_cache.c +++ b/test/test_write_cache.c @@ -39,11 +39,20 @@ struct options { static const struct fuse_opt option_spec[] = { OPTION("writeback_cache", writeback), OPTION("--data-size=%d", data_size), - FUSE_OPT_KEY("writeback_cache", FUSE_OPT_KEY_KEEP), FUSE_OPT_END }; static int got_write; +static void tfs_init (void *userdata, struct fuse_conn_info *conn) +{ + (void) userdata; + + if(options.writeback) { + assert(conn->capable & FUSE_CAP_WRITEBACK_CACHE); + conn->want |= FUSE_CAP_WRITEBACK_CACHE; + } +} + static int tfs_stat(fuse_ino_t ino, struct stat *stbuf) { stbuf->st_ino = ino; if (ino == FUSE_ROOT_ID) { @@ -126,6 +135,7 @@ static void tfs_write(fuse_req_t req, fuse_ino_t ino, const char *buf, } static struct fuse_lowlevel_ops tfs_oper = { + .init = tfs_init, .lookup = tfs_lookup, .getattr = tfs_getattr, .open = tfs_open, -- 2.30.2