summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--netfs/daemon/daemonFile.cpp20
-rw-r--r--netfs/daemon/daemonFile.h1
-rw-r--r--netfs/fuse/fuseApp.h1
-rw-r--r--netfs/fuse/fuseFiles.cpp17
-rw-r--r--netfs/ice/file.ice1
-rw-r--r--netfs/unittests/testCore.cpp16
6 files changed, 56 insertions, 0 deletions
diff --git a/netfs/daemon/daemonFile.cpp b/netfs/daemon/daemonFile.cpp
index 48730bc..ec96bc3 100644
--- a/netfs/daemon/daemonFile.cpp
+++ b/netfs/daemon/daemonFile.cpp
@@ -6,6 +6,7 @@
#include <sys/stat.h>
#include "daemonFile.h"
#include <entCache.h>
+#include <unistd.h>
FileServer::FileServer(int f, EntryTypeConverter & t) :
EntryTypeConverter(t),
@@ -69,3 +70,22 @@ FileServer::write(Ice::Long offset, Ice::Long size, const NetFS::Buffer data, co
}
}
+Ice::Long
+FileServer::copyrange(NetFS::FilePrxPtr to, Ice::Long offsrc, Ice::Long offdst, Ice::Long size, Ice::Int flags, const Ice::Current& ice)
+{
+ if (auto obj = ice.adapter->findByProxy(to);
+ auto file = std::dynamic_pointer_cast<FileServer>(obj)) {
+ errno = 0;
+ off_t src = offsrc, dst = offdst;
+ if (auto rtn = copy_file_range(fd, &src, file->fd, &dst, size, flags);
+ rtn != -1) {
+ return rtn;
+ }
+ throw NetFS::SystemError(errno);
+ }
+ else {
+ to->write(offdst, size, read(offsrc, size, ice));
+ return size;
+ }
+}
+
diff --git a/netfs/daemon/daemonFile.h b/netfs/daemon/daemonFile.h
index ee4ae7d..d61e37d 100644
--- a/netfs/daemon/daemonFile.h
+++ b/netfs/daemon/daemonFile.h
@@ -14,6 +14,7 @@ class FileServer : public NetFS::File, EntryTypeConverter {
virtual NetFS::Buffer read(Ice::Long offset, Ice::Long size, const Ice::Current&) override;
virtual void write(Ice::Long offset, Ice::Long size, const NetFS::Buffer data, const Ice::Current&) override;
+ virtual Ice::Long copyrange(NetFS::FilePrxPtr, Ice::Long, Ice::Long, Ice::Long, Ice::Int, const Ice::Current&) override;
private:
const int fd;
diff --git a/netfs/fuse/fuseApp.h b/netfs/fuse/fuseApp.h
index ca3e631..eec2932 100644
--- a/netfs/fuse/fuseApp.h
+++ b/netfs/fuse/fuseApp.h
@@ -88,6 +88,7 @@ namespace NetFS {
int release(const char *, struct fuse_file_info * fi) override;
int read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) override;
int write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi) override;
+ ssize_t copy_file_range(const char *, struct fuse_file_info *, off_t, const char *, struct fuse_file_info *, off_t, size_t, int) override;
int truncate(const char *, off_t, struct fuse_file_info *) override;
// fs
int statfs(const char *, struct statvfs *) override;
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp
index c166e46..48b3f87 100644
--- a/netfs/fuse/fuseFiles.cpp
+++ b/netfs/fuse/fuseFiles.cpp
@@ -204,6 +204,23 @@ FuseApp::write(const char *, const char * buf, size_t s, off_t o, struct fuse_fi
}
}
+ssize_t
+FuseApp::copy_file_range(const char *, struct fuse_file_info *fi_in, off_t offset_in, const char *, struct fuse_file_info *fi_out, off_t offset_out, size_t size, int flags)
+{
+ try {
+ auto of_in = getProxy<OpenFilePtr>(fi_in->fh);
+ auto of_out = getProxy<OpenFilePtr>(fi_out->fh);
+ auto remote_in = of_in->remote;
+ auto remote_out = of_out->remote;
+ of_in->wait();
+ of_out->wait();
+ return remote_in->copyrange(remote_out, offset_in, offset_out, size, flags);
+ }
+ catch (SystemError & e) {
+ return -e.syserrno;
+ }
+}
+
int
FuseApp::truncate(const char * p, off_t o, fuse_file_info * fi)
{
diff --git a/netfs/ice/file.ice b/netfs/ice/file.ice
index a622745..7a41f18 100644
--- a/netfs/ice/file.ice
+++ b/netfs/ice/file.ice
@@ -12,6 +12,7 @@ module NetFS {
idempotent Buffer read(long offset, long size) throws AuthError, SystemError;
idempotent void ftruncate(ReqEnv env, long size) throws AuthError, SystemError;
idempotent void write(long offset, long size, Buffer data) throws AuthError, SystemError;
+ idempotent long copyrange(File * to, long offsetsrc, long offsetdest, long size, int flags) throws AuthError, SystemError;
};
};
diff --git a/netfs/unittests/testCore.cpp b/netfs/unittests/testCore.cpp
index 0f87b02..ee079a8 100644
--- a/netfs/unittests/testCore.cpp
+++ b/netfs/unittests/testCore.cpp
@@ -297,6 +297,22 @@ BOOST_AUTO_TEST_CASE( files )
BOOST_REQUIRE_EQUAL(fuse->unlink("/test3"), -ENOENT);
}
+BOOST_AUTO_TEST_CASE( files_copy_range )
+{
+ struct fuse_file_info fiin {}, fiout {};
+ fiin.flags = O_RDWR;
+ fiout.flags = O_RDWR;
+ BOOST_REQUIRE_EQUAL(fuse->create("/src", 0600, &fiin), 0);
+ BOOST_REQUIRE_EQUAL(fuse->create("/dst", 0600, &fiout), 0);
+ BOOST_REQUIRE_EQUAL(fuse->write("/src", "hello world.", 12, 0, &fiin), 12);
+ BOOST_REQUIRE_EQUAL(fuse->copy_file_range("/src", &fiin, 6, "/dst", &fiout, 0, 5, 0), 5);
+ std::array<char, 5> buf {};
+ BOOST_REQUIRE_EQUAL(fuse->read("/dst", buf.data(), 5, 0, &fiout), 5);
+ BOOST_REQUIRE_EQUAL(memcmp("world", buf.data(), buf.size()), 0);
+ BOOST_REQUIRE_EQUAL(fuse->release("/src", &fiin), 0);
+ BOOST_REQUIRE_EQUAL(fuse->release("/dst", &fiout), 0);
+}
+
BOOST_AUTO_TEST_CASE( bgwriteOverlapped, * boost::unit_test::timeout(2) )
{
struct fuse_file_info fi {};