diff options
Diffstat (limited to 'netfs/fuse/fuseFiles.cpp')
-rw-r--r-- | netfs/fuse/fuseFiles.cpp | 449 |
1 files changed, 222 insertions, 227 deletions
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp index 48b3f87..0a59252 100644 --- a/netfs/fuse/fuseFiles.cpp +++ b/netfs/fuse/fuseFiles.cpp @@ -1,282 +1,277 @@ -#include <cstring> -#include "fuseApp.impl.h" #include "fuseFiles.h" +#include "fuseApp.impl.h" #include "lockHelpers.h" +#include <cstring> #include <entCache.h> #include <mutex> namespace NetFS { -FuseApp::OpenFile::WriteState::WriteState() : - future(promise.get_future().share()) -{ -} - -FuseApp::OpenFile::OpenFile(FilePrxPtr r, std::string p, int f) : - remote(std::move(r)), - path(std::move(p)), - flags(f) -{ -} - -template<> -std::map<int, FuseApp::OpenFilePtr> & -FuseApp::getMap<FuseApp::OpenFilePtr>() -{ - return openFiles; -} + FuseApp::OpenFile::WriteState::WriteState() : future(promise.get_future().share()) { } -void -FuseApp::OpenFile::wait() const -{ - auto cbg = [this](){ - SharedLock(_lock); - return bg; - }(); - for (const auto & w : cbg) { - w.second->future.wait(); + FuseApp::OpenFile::OpenFile(FilePrxPtr r, std::string p, int f) : remote(std::move(r)), path(std::move(p)), flags(f) + { } -} -void -FuseApp::OpenFile::flush() -{ - auto first = [this]() { - SharedLock(_lock); - return bg.empty() ? nullptr : bg.begin()->second; - }; - while (auto w = first()) { - // background operations are void, so no need to actually get the return value - w->future.wait(); + template<> + std::map<int, FuseApp::OpenFilePtr> & + FuseApp::getMap<FuseApp::OpenFilePtr>() + { + return openFiles; } -} -FuseApp::OpenFile::BGs::interval_type -FuseApp::OpenFile::range(off_t o, size_t s) -{ - return OpenFile::BGs::interval_type::right_open(o, o + s); -} - -int -FuseApp::open(const char * p, struct fuse_file_info * fi) -{ - try { - auto remote = volume->open(reqEnv(), p, fi->flags); - setProxy<OpenFilePtr>(fi->fh, remote, p, fi->flags); - return 0; - } - catch (SystemError & e) { - return -e.syserrno; + void + FuseApp::OpenFile::wait() const + { + auto cbg = [this]() { + SharedLock(_lock); + return bg; + }(); + for (const auto & w : cbg) { + w.second->future.wait(); + } } -} -int -FuseApp::create(const char * p, mode_t m, struct fuse_file_info * fi) -{ - try { - auto remote = volume->create(reqEnv(), p, fi->flags, m); - setProxy<OpenFilePtr>(fi->fh, remote, p, fi->flags); - return 0; + void + FuseApp::OpenFile::flush() + { + auto first = [this]() { + SharedLock(_lock); + return bg.empty() ? nullptr : bg.begin()->second; + }; + while (auto w = first()) { + // background operations are void, so no need to actually get the return value + w->future.wait(); + } } - catch (SystemError & e) { - return -e.syserrno; + + FuseApp::OpenFile::BGs::interval_type + FuseApp::OpenFile::range(off_t o, size_t s) + { + return OpenFile::BGs::interval_type::right_open(o, o + s); } -} -int -FuseApp::release(const char *, struct fuse_file_info * fi) -{ - try { - auto of = getProxy<OpenFilePtr>(fi->fh); - auto remote = of->remote; + int + FuseApp::open(const char * p, struct fuse_file_info * fi) + { try { - of->flush(); + auto remote = volume->open(reqEnv(), p, fi->flags); + setProxy<OpenFilePtr>(fi->fh, remote, p, fi->flags); + return 0; } catch (SystemError & e) { + return -e.syserrno; } - remote->close(); - clearProxy<OpenFilePtr>(fi->fh); - return 0; - } - catch (SystemError & e) { - clearProxy<OpenFilePtr>(fi->fh); - return -e.syserrno; - } -} - -int -FuseApp::flush(const char *, struct fuse_file_info * fi) -{ - try { - getProxy<OpenFilePtr>(fi->fh)->flush(); - return 0; - } - catch (SystemError & e) { - return -e.syserrno; } -} -template<typename Rtn, typename F> -inline -Rtn -FuseApp::waitOnWriteRangeAndThen(size_t s, off_t o, const OpenFilePtr & of, const F & f) -{ - const auto key = OpenFile::range(o, s); - while (true) { - std::unique_lock<decltype(of->_lock)> _l(of->_lock); - // Acquire operations to wait for - auto R = of->bg.equal_range(key); - if (R.first == R.second) { - // Perform operation - return f(key); + int + FuseApp::create(const char * p, mode_t m, struct fuse_file_info * fi) + { + try { + auto remote = volume->create(reqEnv(), p, fi->flags, m); + setProxy<OpenFilePtr>(fi->fh, remote, p, fi->flags); + return 0; } - else { - std::vector<std::shared_ptr<OpenFile::WriteState>> overlap; - overlap.reserve(std::distance(R.first, R.second)); - for (auto i = R.first; i != R.second; i++) { - overlap.push_back(i->second); - } - // Wait for them whilst unlocked - _l.release()->unlock(); - for (const auto & r : overlap) { - r->future.wait(); - } - // Cause this thread to yield so the callback can acquire _lock - usleep(0); + catch (SystemError & e) { + return -e.syserrno; } } -} -int -FuseApp::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) -{ - try { - auto cpy = [buf](const auto && data) { - memcpy(buf, &data.front(), data.size()); - return data.size(); - }; - auto of = getProxy<OpenFilePtr>(fi->fh); - auto remote = of->remote; - if (fcr->Async) { - auto p = waitOnWriteRangeAndThen<std::future<Buffer>>(s, o, of, [o, s, &remote](const auto &){ - return remote->readAsync(o, s); - }); - return cpy(p.get()); + int + FuseApp::release(const char *, struct fuse_file_info * fi) + { + try { + auto of = getProxy<OpenFilePtr>(fi->fh); + auto remote = of->remote; + try { + of->flush(); + } + catch (SystemError & e) { + } + remote->close(); + clearProxy<OpenFilePtr>(fi->fh); + return 0; } - else { - return cpy(remote->read(o, s)); + catch (SystemError & e) { + clearProxy<OpenFilePtr>(fi->fh); + return -e.syserrno; } } - catch (SystemError & e) { - return -e.syserrno; - } -} -int -FuseApp::write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi) -{ - try { - auto of = getProxy<OpenFilePtr>(fi->fh); - auto remote = of->remote; - if (fcr->Async) { - waitOnWriteRangeAndThen<void>(s, o, of, [o, s, buf, &of, remote](const auto & key){ - auto p = std::make_shared<OpenFile::WriteState>(); - remote->writeAsync(o, s, Buffer(buf, buf + s), [p,of,key]() { - p->promise.set_value(); - ScopeLock(of->_lock) { - of->bg.erase(key); - } - }, [p,of,key](auto e) { - p->promise.set_exception(e); - ScopeLock(of->_lock) { - of->bg.erase(key); - } - }); - of->bg.insert({key, p}); - }); + int + FuseApp::flush(const char *, struct fuse_file_info * fi) + { + try { + getProxy<OpenFilePtr>(fi->fh)->flush(); + return 0; } - else { - remote->write(o, s, Buffer(buf, buf + s)); + catch (SystemError & e) { + return -e.syserrno; } - return s; - } - catch (SystemError & e) { - return -e.syserrno; } -} -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; + template<typename Rtn, typename F> + inline Rtn + FuseApp::waitOnWriteRangeAndThen(size_t s, off_t o, const OpenFilePtr & of, const F & f) + { + const auto key = OpenFile::range(o, s); + while (true) { + std::unique_lock<decltype(of->_lock)> _l(of->_lock); + // Acquire operations to wait for + auto R = of->bg.equal_range(key); + if (R.first == R.second) { + // Perform operation + return f(key); + } + else { + std::vector<std::shared_ptr<OpenFile::WriteState>> overlap; + overlap.reserve(std::distance(R.first, R.second)); + for (auto i = R.first; i != R.second; i++) { + overlap.push_back(i->second); + } + // Wait for them whilst unlocked + _l.release()->unlock(); + for (const auto & r : overlap) { + r->future.wait(); + } + // Cause this thread to yield so the callback can acquire _lock + usleep(0); + } + } } -} -int -FuseApp::truncate(const char * p, off_t o, fuse_file_info * fi) -{ - try { - if (fi) { + int + FuseApp::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) + { + try { + auto cpy = [buf](const auto && data) { + memcpy(buf, &data.front(), data.size()); + return data.size(); + }; auto of = getProxy<OpenFilePtr>(fi->fh); - of->wait(); auto remote = of->remote; - remote->ftruncate(reqEnv(), o); + if (fcr->Async) { + auto p = waitOnWriteRangeAndThen<std::future<Buffer>>(s, o, of, [o, s, &remote](const auto &) { + return remote->readAsync(o, s); + }); + return cpy(p.get()); + } + else { + return cpy(remote->read(o, s)); + } } - else { - volume->truncate(reqEnv(), p, o); + catch (SystemError & e) { + return -e.syserrno; } - return 0; - } - catch (SystemError & e) { - return -e.syserrno; } -} -int -FuseApp::getattr(const char * p, struct stat * s, fuse_file_info * fi) -{ - try { - if (fi) { + int + FuseApp::write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi) + { + try { auto of = getProxy<OpenFilePtr>(fi->fh); - of->wait(); auto remote = of->remote; - *s = converter.convert(remote->fgetattr(reqEnv())); - } - else { - if (auto cacehedStat = statCache.get(p)) { - *s = *cacehedStat; + if (fcr->Async) { + waitOnWriteRangeAndThen<void>(s, o, of, [o, s, buf, &of, remote](const auto & key) { + auto p = std::make_shared<OpenFile::WriteState>(); + remote->writeAsync( + o, s, Buffer(buf, buf + s), + [p, of, key]() { + p->promise.set_value(); + ScopeLock(of->_lock) { + of->bg.erase(key); + } + }, + [p, of, key](auto e) { + p->promise.set_exception(e); + ScopeLock(of->_lock) { + of->bg.erase(key); + } + }); + of->bg.insert({key, p}); + }); } else { - *s = converter.convert(volume->getattr(reqEnv(), p)); + remote->write(o, s, Buffer(buf, buf + s)); } + return s; + } + catch (SystemError & e) { + return -e.syserrno; + } + } + 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; } - return 0; } - catch (SystemError & e) { - return -e.syserrno; + + int + FuseApp::truncate(const char * p, off_t o, fuse_file_info * fi) + { + try { + if (fi) { + auto of = getProxy<OpenFilePtr>(fi->fh); + of->wait(); + auto remote = of->remote; + remote->ftruncate(reqEnv(), o); + } + else { + volume->truncate(reqEnv(), p, o); + } + return 0; + } + catch (SystemError & e) { + return -e.syserrno; + } } -} -int -FuseApp::unlink(const char * p) -{ - try { - volume->unlink(reqEnv(), p); - return 0; + int + FuseApp::getattr(const char * p, struct stat * s, fuse_file_info * fi) + { + try { + if (fi) { + auto of = getProxy<OpenFilePtr>(fi->fh); + of->wait(); + auto remote = of->remote; + *s = converter.convert(remote->fgetattr(reqEnv())); + } + else { + if (auto cacehedStat = statCache.get(p)) { + *s = *cacehedStat; + } + else { + *s = converter.convert(volume->getattr(reqEnv(), p)); + } + } + return 0; + } + catch (SystemError & e) { + return -e.syserrno; + } } - catch (SystemError & e) { - return -e.syserrno; + + int + FuseApp::unlink(const char * p) + { + try { + volume->unlink(reqEnv(), p); + return 0; + } + catch (SystemError & e) { + return -e.syserrno; + } } } -} - |