From b488ce077ce235d4e05be8c9b1bd7d6748599a54 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 1 Jan 2018 20:35:13 +0000 Subject: Refactor to allow read to only wait on overlapping writes --- netfs/fuse/fuseApp.h | 3 ++ netfs/fuse/fuseFiles.cpp | 73 ++++++++++++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/netfs/fuse/fuseApp.h b/netfs/fuse/fuseApp.h index 9486e41..41ff9ad 100644 --- a/netfs/fuse/fuseApp.h +++ b/netfs/fuse/fuseApp.h @@ -115,6 +115,9 @@ namespace NetFS { template std::map & getMap(); + template static inline Rtn + waitOnWriteRangeAndThen(size_t s, off_t o, const OpenFilePtr & of, const F & f); + ReqEnv reqEnv(); Ice::StringSeq args; diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp index b587809..222cab0 100644 --- a/netfs/fuse/fuseFiles.cpp +++ b/netfs/fuse/fuseFiles.cpp @@ -106,14 +106,47 @@ FuseApp::flush(const char *, struct fuse_file_info * fi) } } +template +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_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 { + // Wait for them whilst unlocked + _l.release()->unlock(); + std::vector overlap; + overlap.reserve(std::distance(R.first, R.second)); + for (auto i = R.first; i != R.second; i++) { + overlap.push_back(i->second); + } + for (const auto & r : overlap) { + r->waitForCompleted(); + } + // Cause this thread to yield so the callback can acquire _lock + usleep(0); + } + } +} + int FuseApp::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) { try { auto of = getProxy(fi->fh); - of->wait(); auto remote = of->remote; - Buffer data = remote->read(o, s); + auto data = (fcr->Async) ? + waitOnWriteRangeAndThen(s, o, of, [o, s, &remote](const auto &){ + return remote->read(o, s); + }) : remote->read(o, s); memcpy(buf, &data.front(), data.size()); return data.size(); } @@ -129,36 +162,14 @@ FuseApp::write(const char *, const char * buf, size_t s, off_t o, struct fuse_fi auto of = getProxy(fi->fh); auto remote = of->remote; if (fcr->Async) { - const auto key = OpenFile::range(o, s); - while (true) { - std::unique_lock_lock)> _l(of->_lock); - // Acquire operations to wait for - std::vector overlap; - auto R = of->bg.equal_range(key); - if (R.first == R.second) { - // Begin write and store operation - auto r = remote->begin_write(o, s, Buffer(buf, buf + s), [of,key](const Ice::AsyncResultPtr &) { - ScopeLock(of->_lock) { - of->bg.erase(key); - } - }); - of->bg.insert({key, r}); - break; - } - else { - // Wait for them whilst unlocked - _l.release()->unlock(); - overlap.reserve(std::distance(R.first, R.second)); - for (auto i = R.first; i != R.second; i++) { - overlap.push_back(i->second); - } - for (const auto & r : overlap) { - r->waitForCompleted(); + waitOnWriteRangeAndThen(s, o, of, [o, s, buf, &of, &remote](const auto & key){ + auto r = remote->begin_write(o, s, Buffer(buf, buf + s), [of,key](const Ice::AsyncResultPtr &) { + ScopeLock(of->_lock) { + of->bg.erase(key); } - // Cause this thread to yield so the callback can acquire _lock - usleep(0); - } - } + }); + of->bg.insert({key, r}); + }); } else { remote->write(o, s, Buffer(buf, buf + s)); -- cgit v1.2.3