diff options
author | Alessio Balsini <balsini@google.com> | 2020-07-01 14:14:28 +0100 |
---|---|---|
committer | Alessio Balsini <balsini@google.com> | 2020-11-12 19:31:48 +0000 |
commit | 74ea28e46b6860a7663341a4268d6685699e302f (patch) | |
tree | 055ee0ab46564340653c868355e99db244210fcc /lib | |
parent | 5d3920545beef6b010e555fbd19a94b3d3e056d9 (diff) | |
download | libfuse-74ea28e46b6860a7663341a4268d6685699e302f.tar.gz |
Enable passthrough mode for read/write operations
Add support for filesystem passthrough read/write of files.
When the FUSE_PASSTHROUGH capability is enabled, the FUSE daemon may
decide while handling the "open" or "create" operation, if the given
file can be accessed by that process in "passthrough" mode, meaning that
all the further read and write operations would be forwarded by the
kernel directly to the lower filesystem rather than to the FUSE daemon.
All requests that aren't read or write are still handled by the
userspace code.
This allows for an improved performance on reads and writes, especially
in the case of reads at random offsets, for which no (readahead)
caching mechanism would help, reducing the performance gap between FUSE
and native filesystem access.
Extend also the passthrough_hp example with the new passthrough feature.
Bug: 168023149
Test: atest ScopedStorageTest
Signed-off-by: Alessio Balsini <balsini@android.com>
Change-Id: I38aff0cf7198b7cd92eccc97547d47f4e1132b00
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fuse_lowlevel.c | 19 | ||||
-rw-r--r-- | lib/fuse_versionscript | 1 |
2 files changed, 20 insertions, 0 deletions
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index fc76b7c..c7efc3d 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -27,6 +27,7 @@ #include <errno.h> #include <assert.h> #include <sys/file.h> +#include <sys/ioctl.h> #ifndef F_LINUX_SPECIFIC_BASE #define F_LINUX_SPECIFIC_BASE 1024 @@ -388,6 +389,7 @@ static void fill_open(struct fuse_open_out *arg, const struct fuse_file_info *f) { arg->fh = f->fh; + arg->passthrough_fh = f->passthrough_fh; if (f->direct_io) arg->open_flags |= FOPEN_DIRECT_IO; if (f->keep_cache) @@ -457,6 +459,19 @@ int fuse_reply_canonical_path(fuse_req_t req, const char *path) return send_reply_ok(req, path, strlen(path) + 1); } +int fuse_passthrough_enable(fuse_req_t req, unsigned int fd) { + struct fuse_passthrough_out out = {}; + int ret; + + out.fd = fd; + + ret = ioctl(req->se->fd, FUSE_DEV_IOC_PASSTHROUGH_OPEN, &out); + if (ret <= 0) + fuse_log(FUSE_LOG_ERR, "fuse: passthrough_enable: %s\n", strerror(errno)); + + return ret; +} + int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f) { struct fuse_open_out arg; @@ -1990,6 +2005,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) bufsize = max_bufsize; } } + if (arg->flags & FUSE_PASSTHROUGH) + se->conn.capable |= FUSE_PASSTHROUGH; } else { se->conn.max_readahead = 0; } @@ -2102,6 +2119,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_WRITEBACK_CACHE; if (se->conn.want & FUSE_CAP_POSIX_ACL) outarg.flags |= FUSE_POSIX_ACL; + if (se->conn.want & FUSE_CAP_PASSTHROUGH) + outarg.flags |= FUSE_PASSTHROUGH; outarg.max_readahead = se->conn.max_readahead; outarg.max_write = se->conn.max_write; if (se->conn.proto_minor >= 13) { diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index 4c075a3..b01699a 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -163,6 +163,7 @@ FUSE_3.7 { global: fuse_set_log_func; fuse_log; + fuse_passthrough_enable; fuse_reply_canonical_path; } FUSE_3.3; |