summaryrefslogtreecommitdiff
path: root/netfs/fuse/fuseFiles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netfs/fuse/fuseFiles.cpp')
-rw-r--r--netfs/fuse/fuseFiles.cpp449
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;
+ }
}
}
-}
-