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.
This commit is contained in:
Niels de Vos 2018-06-26 21:40:21 +02:00 committed by Nikolaus Rath
parent fe4f9428fc
commit 2548c4b83a
7 changed files with 108 additions and 4 deletions

View 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)
==========================

View 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[])

View 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[])

View 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[])

View 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' ])

View 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))

View 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')