From 1fd518aac79d26a4cd40d7d0b99f7302c45a97c7 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 29 Mar 2020 10:40:39 +0100 Subject: Implement copy range --- netfs/daemon/daemonFile.cpp | 20 ++++++++++++++++++++ netfs/daemon/daemonFile.h | 1 + netfs/fuse/fuseApp.h | 1 + netfs/fuse/fuseFiles.cpp | 17 +++++++++++++++++ netfs/ice/file.ice | 1 + netfs/unittests/testCore.cpp | 16 ++++++++++++++++ 6 files changed, 56 insertions(+) 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 #include "daemonFile.h" #include +#include 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(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(fi_in->fh); + auto of_out = getProxy(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 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 {}; -- cgit v1.2.3