examples: add copy_file_range() support to passthrough(_fh)
authorNiels de Vos <ndevos@redhat.com>
Tue, 26 Jun 2018 19:40:21 +0000 (21:40 +0200)
committerNikolaus Rath <Nikolaus@rath.org>
Mon, 19 Nov 2018 12:33:56 +0000 (12:33 +0000)
The passthrough example filesystem can be used for validating the API
and the implementation in the FUSE kernel module.

ChangeLog.rst
example/passthrough.c
example/passthrough_fh.c
example/passthrough_ll.c
lib/meson.build
meson.build
util/meson.build

index 8ea939734bf08d3f2a6a50066974241505adb2ff..9dc8b3d3b21556c4cacd225ddad0824610c0edb6 100644 (file)
@@ -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)
 ==========================
 
index b83c17f92429a1ddd592755603d8d7baab2297a8..da91930bd5403edf61c88475176175be7187c276 100644 (file)
@@ -29,6 +29,8 @@
 #include <config.h>
 #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[])
index 2b1ed1c492ba04454778ab3484d9d5be6015136a..3fc80f8f75dab77d01ff143dc26271036968881a 100644 (file)
@@ -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[])
index 40913956a66696e64980dd8f6b971d6804cca800..5cca53170c07e0eeff61a23953ef5a6c3d55d702 100644 (file)
@@ -37,6 +37,8 @@
 #define _GNU_SOURCE
 #define FUSE_USE_VERSION 31
 
+#include "config.h"
+
 #include <fuse_lowlevel.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -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[])
index 996bcfd484dd07bc1f1f3c4592163b274896bb77..90ce5a46ecfdfbe1246440702a39de93bbb78591 100644 (file)
@@ -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' ])
index 661811a2d758c2f950f46302775661411763d1f3..58c4c257e1990af4e2f745199802aa8086b0dd8e 100644 (file)
@@ -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))
index e8105bd8251f2e20c6e57942475800893501dee5..aa0e734a3d929594b0420693c5470b9c6ffd0ffd 100644 (file)
@@ -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')