From 2548c4b83a0871fb92b8ca55cf580a7c58c2f9c6 Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Tue, 26 Jun 2018 21:40:21 +0200 Subject: [PATCH] examples: add copy_file_range() support to passthrough(_fh) The passthrough example filesystem can be used for validating the API and the implementation in the FUSE kernel module. --- ChangeLog.rst | 6 ++++++ example/passthrough.c | 45 ++++++++++++++++++++++++++++++++++++++++ example/passthrough_fh.c | 23 ++++++++++++++++++++ example/passthrough_ll.c | 30 +++++++++++++++++++++++++++ lib/meson.build | 2 +- meson.build | 4 ++-- util/meson.build | 2 +- 7 files changed, 108 insertions(+), 4 deletions(-) diff --git a/ChangeLog.rst b/ChangeLog.rst index 8ea9397..9dc8b3d 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -1,3 +1,9 @@ +libfuse 3.4.0 +============= + +* Add `copy_file_range()` to support efficient copying of data from one file to + an other. + libfuse 3.3.0 (2018-11-06) ========================== diff --git a/example/passthrough.c b/example/passthrough.c index b83c17f..da91930 100644 --- a/example/passthrough.c +++ b/example/passthrough.c @@ -29,6 +29,8 @@ #include #endif +#define _GNU_SOURCE + #ifdef linux /* For pread()/pwrite()/utimensat() */ #define _XOPEN_SOURCE 700 @@ -445,6 +447,46 @@ static int xmp_removexattr(const char *path, const char *name) } #endif /* HAVE_SETXATTR */ +#ifdef HAVE_COPY_FILE_RANGE +static ssize_t xmp_copy_file_range(const char *path_in, + struct fuse_file_info *fi_in, + off_t offset_in, const char *path_out, + struct fuse_file_info *fi_out, + off_t offset_out, size_t len, int flags) +{ + int fd_in, fd_out; + ssize_t res; + + if(fi_in == NULL) + fd_in = open(path_in, O_RDONLY); + else + fd_in = fi_in->fh; + + if (fd_in == -1) + return -errno; + + if(fi_out == NULL) + fd_out = open(path_out, O_WRONLY); + else + fd_out = fi_out->fh; + + if (fd_out == -1) { + close(fd_in); + return -errno; + } + + res = copy_file_range(fd_in, &offset_in, fd_out, &offset_out, len, + flags); + if (res == -1) + res = -errno; + + close(fd_in); + close(fd_out); + + return res; +} +#endif + static struct fuse_operations xmp_oper = { .init = xmp_init, .getattr = xmp_getattr, @@ -480,6 +522,9 @@ static struct fuse_operations xmp_oper = { .listxattr = xmp_listxattr, .removexattr = xmp_removexattr, #endif +#ifdef HAVE_COPY_FILE_RANGE + .copy_file_range = xmp_copy_file_range, +#endif }; int main(int argc, char *argv[]) diff --git a/example/passthrough_fh.c b/example/passthrough_fh.c index 2b1ed1c..3fc80f8 100644 --- a/example/passthrough_fh.c +++ b/example/passthrough_fh.c @@ -576,6 +576,26 @@ static int xmp_flock(const char *path, struct fuse_file_info *fi, int op) return 0; } +#ifdef HAVE_COPY_FILE_RANGE +static ssize_t xmp_copy_file_range(const char *path_in, + struct fuse_file_info *fi_in, + off_t off_in, const char *path_out, + struct fuse_file_info *fi_out, + off_t off_out, size_t len, int flags) +{ + ssize_t res; + (void) path_in; + (void) path_out; + + res = copy_file_range(fi_in->fh, &off_in, fi_out->fh, &off_out, len, + flags); + if (res == -1) + return -errno; + + return res; +} +#endif + static struct fuse_operations xmp_oper = { .init = xmp_init, .getattr = xmp_getattr, @@ -620,6 +640,9 @@ static struct fuse_operations xmp_oper = { .lock = xmp_lock, #endif .flock = xmp_flock, +#ifdef HAVE_COPY_FILE_RANGE + .copy_file_range = xmp_copy_file_range, +#endif }; int main(int argc, char *argv[]) diff --git a/example/passthrough_ll.c b/example/passthrough_ll.c index 4091395..5cca531 100644 --- a/example/passthrough_ll.c +++ b/example/passthrough_ll.c @@ -37,6 +37,8 @@ #define _GNU_SOURCE #define FUSE_USE_VERSION 31 +#include "config.h" + #include #include #include @@ -1121,6 +1123,31 @@ out: fuse_reply_err(req, saverr); } +#ifdef HAVE_COPY_FILE_RANGE +static void lo_copy_file_range(fuse_req_t req, fuse_ino_t ino_in, off_t off_in, + struct fuse_file_info *fi_in, + fuse_ino_t ino_out, off_t off_out, + struct fuse_file_info *fi_out, size_t len, + int flags) +{ + ssize_t res; + + if (lo_debug(req)) + fprintf(stderr, "lo_copy_file_range(ino=%" PRIu64 "/fd=%lu, " + "off=%lu, ino=%" PRIu64 "/fd=%lu, " + "off=%lu, size=%zd, flags=0x%x)\n", + ino_in, fi_in->fh, off_in, ino_out, fi_out->fh, off_out, + len, flags); + + res = copy_file_range(fi_in->fh, &off_in, fi_out->fh, &off_out, len, + flags); + if (res < 0) + fuse_reply_err(req, -errno); + else + fuse_reply_write(req, res); +} +#endif + static struct fuse_lowlevel_ops lo_oper = { .init = lo_init, .lookup = lo_lookup, @@ -1155,6 +1182,9 @@ static struct fuse_lowlevel_ops lo_oper = { .listxattr = lo_listxattr, .setxattr = lo_setxattr, .removexattr = lo_removexattr, +#ifdef HAVE_COPY_FILE_RANGE + .copy_file_range = lo_copy_file_range, +#endif }; int main(int argc, char *argv[]) diff --git a/lib/meson.build b/lib/meson.build index 996bcfd..90ce5a4 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -32,7 +32,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=33', + c_args: [ '-DFUSE_USE_VERSION=34', '-DFUSERMOUNT_DIR="@0@"'.format(fusermount_path) ], link_args: ['-Wl,--version-script,' + meson.current_source_dir() + '/fuse_versionscript' ]) diff --git a/meson.build b/meson.build index 661811a..58c4c25 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('libfuse3', 'c', version: '3.3.0', +project('libfuse3', 'c', version: '3.4.0', meson_version: '>= 0.42', default_options: [ 'buildtype=debugoptimized' ]) @@ -36,7 +36,7 @@ cfg.set_quoted('PACKAGE_VERSION', meson.project_version()) # Test for presence of some functions test_funcs = [ 'fork', 'fstatat', 'openat', 'readlinkat', 'pipe2', 'splice', 'vmsplice', 'posix_fallocate', 'fdatasync', - 'utimensat' ] + 'utimensat', 'copy_file_range' ] foreach func : test_funcs cfg.set('HAVE_' + func.to_upper(), cc.has_function(func, prefix: include_default, args: args_default)) diff --git a/util/meson.build b/util/meson.build index e8105bd..aa0e734 100644 --- a/util/meson.build +++ b/util/meson.build @@ -11,7 +11,7 @@ executable('mount.fuse3', ['mount.fuse.c'], link_with: [ libfuse ], install: true, install_dir: get_option('sbindir'), - c_args: '-DFUSE_USE_VERSION=33') + c_args: '-DFUSE_USE_VERSION=34') udevrulesdir = get_option('udevrulesdir') -- 2.30.2