diff options
| -rw-r--r-- | netfs/fuse/fuseApp.h | 3 | ||||
| -rw-r--r-- | 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<typename Handle>  			std::map<int, Handle> & getMap(); +			template<typename Rtn, typename F> 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<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 { +			// Wait for them whilst unlocked +			_l.release()->unlock(); +			std::vector<Ice::AsyncResultPtr> 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<OpenFilePtr>(fi->fh); -		of->wait();  		auto remote = of->remote; -		Buffer data = remote->read(o, s); +		auto data = (fcr->Async) ? +			waitOnWriteRangeAndThen<Buffer>(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<OpenFilePtr>(fi->fh);  		auto remote = of->remote;  		if (fcr->Async) { -			const auto key = OpenFile::range(o, s); -			while (true) { -				std::unique_lock<decltype(of->_lock)> _l(of->_lock); -				// Acquire operations to wait for -				std::vector<Ice::AsyncResultPtr> 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<void>(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));  | 
