diff options
Diffstat (limited to 'netfs/fuse/fuseFiles.cpp')
-rw-r--r-- | netfs/fuse/fuseFiles.cpp | 326 |
1 files changed, 158 insertions, 168 deletions
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp index 149e8b3..a3c9dd4 100644 --- a/netfs/fuse/fuseFiles.cpp +++ b/netfs/fuse/fuseFiles.cpp @@ -1,12 +1,10 @@ #include "fuseFiles.h" -#include "fuseApp.impl.h" +#include "fuseApp.impl.h" // IWYU pragma: keep - getProxy definition #include "lockHelpers.h" #include <Ice/BuiltinSequences.h> #include <algorithm> -#include <atomic> #include <cstring> #include <entCache.h> -#include <exception> #include <functional> #include <future> #include <iterator> @@ -20,8 +18,8 @@ namespace NetFS { FuseApp::OpenFile::WriteState::WriteState() : future(promise.get_future().share()) { } - FuseApp::OpenFile::OpenFile(FilePrxPtr r, std::string p, int f, size_t mms) : - remote(std::move(r)), path(std::move(p)), flags(f), bodyMaxSize(mms - 1024) + FuseApp::OpenFile::OpenFile(FilePrxPtr remotePrx, std::string remotePath, int openFlags, size_t messageMaxSize) : + remote(std::move(remotePrx)), path(std::move(remotePath)), flags(openFlags), bodyMaxSize(messageMaxSize - 1024) { } @@ -39,35 +37,35 @@ namespace NetFS { SharedLock(mutex); return bg; }(); - for (const auto & w : cbg) { - w.second->future.get(); + for (const auto & operation : cbg) { + operation.second->future.get(); } } void FuseApp::OpenFile::flush() { - auto first = [this]() { + auto getFirstBackgroundOp = [this]() { SharedLock(mutex); return bg.empty() ? nullptr : bg.begin()->second; }; - while (auto w = first()) { - w->future.get(); + while (auto operation = getFirstBackgroundOp()) { + operation->future.get(); } } FuseApp::OpenFile::BGs::interval_type - FuseApp::OpenFile::range(off_t o, size_t s) + FuseApp::OpenFile::range(off_t offset, size_t size) { - return OpenFile::BGs::interval_type::right_open(safe {o}, safe {o} + s); + return OpenFile::BGs::interval_type::right_open(safe {offset}, safe {offset} + size); } int - FuseApp::open(const char * p, struct fuse_file_info * fi) + FuseApp::open(const char * path, struct fuse_file_info * fileInfo) { try { - auto remote = volume->open(reqEnv(), p, fi->flags); - setProxy<OpenFilePtr>(fi->fh, remote, p, fi->flags, combinedSettings.MessageSizeMax); + auto remote = volume->open(reqEnv(), path, fileInfo->flags); + setProxy<OpenFilePtr>(fileInfo->fh, remote, path, fileInfo->flags, combinedSettings.messageSizeMax); return 0; } catch (SystemError & e) { @@ -76,11 +74,11 @@ namespace NetFS { } int - FuseApp::create(const char * p, mode_t m, struct fuse_file_info * fi) + FuseApp::create(const char * path, mode_t mode, struct fuse_file_info * fileInfo) { try { - auto remote = volume->create(reqEnv(), p, fi->flags, safe {m}); - setProxy<OpenFilePtr>(fi->fh, remote, p, fi->flags, combinedSettings.MessageSizeMax); + auto remote = volume->create(reqEnv(), path, fileInfo->flags, safe {mode}); + setProxy<OpenFilePtr>(fileInfo->fh, remote, path, fileInfo->flags, combinedSettings.messageSizeMax); return 0; } catch (SystemError & e) { @@ -89,34 +87,34 @@ namespace NetFS { } int - FuseApp::release(const char *, struct fuse_file_info * fi) + FuseApp::release(const char *, struct fuse_file_info * fileInfo) { try { - auto of = getProxy<OpenFilePtr>(fi->fh); - auto remote = of->remote; + auto openFile = getProxy<OpenFilePtr>(fileInfo->fh); + auto remote = openFile->remote; try { - of->flush(); - clearProxy<OpenFilePtr>(fi->fh); + openFile->flush(); + clearProxy<OpenFilePtr>(fileInfo->fh); remote->close(); } catch (SystemError & e) { - clearProxy<OpenFilePtr>(fi->fh); + clearProxy<OpenFilePtr>(fileInfo->fh); remote->close(); throw; } return 0; } catch (SystemError & e) { - clearProxy<OpenFilePtr>(fi->fh); + clearProxy<OpenFilePtr>(fileInfo->fh); return -e.syserrno; } } int - FuseApp::flush(const char *, struct fuse_file_info * fi) + FuseApp::flush(const char *, struct fuse_file_info * fileInfo) { try { - getProxy<OpenFilePtr>(fi->fh)->flush(); + getProxy<OpenFilePtr>(fileInfo->fh)->flush(); return 0; } catch (SystemError & e) { @@ -124,68 +122,67 @@ namespace NetFS { } } - template<typename F> + template<typename Callback> inline auto - FuseApp::waitOnWriteRangeAndThen(size_t s, off_t o, const OpenFilePtr & of, const F & f) + FuseApp::waitOnWriteRangeAndThen(size_t size, off_t offset, const OpenFilePtr & openFile, const Callback & callback) { - const auto key = OpenFile::range(o, s); + const auto key = OpenFile::range(offset, size); while (true) { - std::unique_lock lock(of->mutex); + std::unique_lock lock(openFile->mutex); // Acquire operations to wait for - const auto R = of->bg.equal_range(key); - if (R.first == R.second) { + const auto pendingRange = openFile->bg.equal_range(key); + if (pendingRange.first == pendingRange.second) { // Perform operation - return f(key); + return callback(key); } - else { - const auto overlap = [R]() { - std::vector<std::shared_future<void>> out; - out.reserve(safe<ptrdiff_t> {std::distance(R.first, R.second)}); - std::transform(R.first, R.second, std::back_inserter(out), [](auto && i) { - return i.second->future; - }); - return out; - }(); - // Wait for them whilst unlocked - lock.release()->unlock(); - try { - std::for_each(overlap.begin(), overlap.end(), [](auto && r) { - r.get(); - }); - } - catch (const SystemError &) { - throw; - } - catch (...) { - throw SystemError {ECOMM}; - } - // Cause this thread to yield so the callback can lock mutex - usleep(0); + const auto overlap = [pendingRange]() { + std::vector<std::shared_future<void>> out; + out.reserve(safe<ptrdiff_t> {std::distance(pendingRange.first, pendingRange.second)}); + std::transform(pendingRange.first, pendingRange.second, std::back_inserter(out), [](auto && operation) { + return operation.second->future; + }); + return out; + }(); + // Wait for them whilst unlocked + lock.release()->unlock(); + try { + std::for_each(overlap.begin(), overlap.end(), [](auto && operationFuture) { + operationFuture.get(); + }); } + catch (const SystemError &) { + throw; + } + catch (...) { + throw SystemError {ECOMM}; + } + // Cause this thread to yield so the callback can lock mutex + usleep(0); } } - template<typename CB> - void - blockSizeIterate(FuseApp::OpenFile::BlockSizes bs, CB && cb) - { - if (bs.size1) { - cb(bs.size1); - } - while (bs.N--) { - cb(bs.sizeN); + namespace { + void + blockSizeIterate(FuseApp::OpenFile::BlockSizes blockSizes, auto && callback) + { + if (blockSizes.size1) { + callback(blockSizes.size1); + } + while (blockSizes.count--) { + callback(blockSizes.sizeN); + } } - } - template<typename T> - auto - operator++(std::vector<std::unique_ptr<T>> & v) - { - return v.emplace_back(std::make_unique<T>()).get(); + template<typename T> + auto + appendNewDefault(std::vector<std::unique_ptr<T>> & container) + { + return container.emplace_back(std::make_unique<T>()).get(); + } } int - FuseApp::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) + FuseApp::read(const char *, char * buf, size_t size, off_t offset, struct fuse_file_info * fileInfo) { try { using BackgroundOps = std::vector<std::unique_ptr<std::promise<int>>>; @@ -195,58 +192,57 @@ namespace NetFS { return safe {data.size()}; }; auto collateTotal = [](auto && ops) { - return std::accumulate(ops.begin(), ops.end(), 0, [](auto && total, auto & op) { - return total += op->get_future().get(); + return std::accumulate(ops.begin(), ops.end(), 0, [](auto && total, auto & operation) { + return total += operation->get_future().get(); }); }; - auto of = getProxy<OpenFilePtr>(fi->fh); - auto remote = of->remote; - auto blockSizes = of->blockSizes(s); + auto openFile = getProxy<OpenFilePtr>(fileInfo->fh); + auto remote = openFile->remote; + auto blockSizes = openFile->blockSizes(size); if (fcr->Async) { BackgroundFuncs fs; BackgroundOps ops; blockSizeIterate(blockSizes, - [&ops, &fs, &o, &of, &remote, blockOffset = 0U, &cpy](safe<size_t> blockSize) mutable { - const auto p = ++ops; - fs.push_back(waitOnWriteRangeAndThen( - blockSize, o, of, [p, o, blockOffset, blockSize, &remote, &cpy](const auto &) { + [&ops, &fs, &offset, &openFile, &remote, blockOffset = 0U, &cpy]( + safe<size_t> blockSize) mutable { + const auto p = appendNewDefault(ops); + fs.push_back(waitOnWriteRangeAndThen(blockSize, offset, openFile, + [p, offset, blockOffset, blockSize, &remote, &cpy](const auto &) { return remote->readAsync( - o, blockSize, + offset, blockSize, [cpy, p, blockOffset](auto && resultBuf) { p->set_value( cpy(blockOffset, std::forward<Ice::ByteSeq>(resultBuf))); }, - [p](auto ex) { - p->set_exception(ex); + [p](auto error) { + p->set_exception(std::move(error)); }); })); - o += blockSize; + offset += blockSize; blockOffset += blockSize; }); return collateTotal(ops); } - else if (of->bodyMaxSize < s) { + if (openFile->bodyMaxSize < size) { BackgroundFuncs fs; BackgroundOps ops; - blockSizeIterate( - blockSizes, [&o, &remote, blockOffset = 0U, &ops, &fs, &cpy](safe<size_t> blockSize) mutable { - const auto p = ++ops; + blockSizeIterate(blockSizes, + [&offset, &remote, blockOffset = 0U, &ops, &fs, &cpy](safe<size_t> blockSize) mutable { + const auto p = appendNewDefault(ops); fs.push_back(remote->readAsync( - o, blockSize, + offset, blockSize, [cpy, p, blockOffset](auto && resultBuf) { p->set_value(cpy(blockOffset, std::forward<Ice::ByteSeq>(resultBuf))); }, - [p](auto ex) { - p->set_exception(ex); + [p](auto error) { + p->set_exception(std::move(error)); })); - o += blockSize; + offset += blockSize; blockOffset += blockSize; }); return collateTotal(ops); } - else { - return cpy(0, remote->read(o, safe {s})); - } + return cpy(0, remote->read(offset, safe {size})); } catch (SystemError & e) { return -e.syserrno; @@ -254,48 +250,48 @@ namespace NetFS { } int - FuseApp::write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi) + FuseApp::write(const char *, const char * buf, size_t size, off_t offset, struct fuse_file_info * fileInfo) { try { - auto of = getProxy<OpenFilePtr>(fi->fh); - auto remote = of->remote; + auto openFile = getProxy<OpenFilePtr>(fileInfo->fh); + auto remote = openFile->remote; auto bytes = reinterpret_cast<const ::Ice::Byte *>(buf); if (fcr->Async) { - blockSizeIterate(of->blockSizes(s), [&bytes, &o, &remote, &of](safe<size_t> blockSize) { - waitOnWriteRangeAndThen(blockSize, o, of, [o, blockSize, bytes, &of, remote](const auto & key) { - auto p = std::make_shared<OpenFile::WriteState>(); - of->bg.insert({key, p}); - remote->writeAsync( - o, blockSize, std::make_pair(bytes, bytes + blockSize), - [p, of, key]() { - p->promise.set_value(); - ScopeLock(of->mutex) { - of->bg.erase(key); - } - }, - [p, of](auto e) { - p->promise.set_exception(e); - }); - }); - bytes += blockSize; - o += blockSize; - }); + blockSizeIterate( + openFile->blockSizes(size), [&bytes, &offset, &remote, &openFile](safe<size_t> blockSize) { + waitOnWriteRangeAndThen(blockSize, offset, openFile, + [offset, blockSize, bytes, &openFile, remote](const auto & key) { + auto p = std::make_shared<OpenFile::WriteState>(); + openFile->bg.insert({key, p}); + remote->writeAsync( + offset, blockSize, std::make_pair(bytes, bytes + blockSize), + [p, openFile, key]() { + p->promise.set_value(); + ScopeLock(openFile->mutex) { + openFile->bg.erase(key); + } + }, + [p, openFile](auto error) { + p->promise.set_exception(std::move(error)); + }); + }); + bytes += blockSize; + offset += blockSize; + }); } - else if (of->bodyMaxSize < s) { + else if (openFile->bodyMaxSize < size) { std::vector<std::future<void>> ops; - blockSizeIterate(of->blockSizes(s), [&ops, &bytes, &o, &remote](safe<size_t> blockSize) { - ops.emplace_back(remote->writeAsync(o, blockSize, std::make_pair(bytes, bytes + blockSize))); + blockSizeIterate(openFile->blockSizes(size), [&ops, &bytes, &offset, &remote](safe<size_t> blockSize) { + ops.emplace_back(remote->writeAsync(offset, blockSize, std::make_pair(bytes, bytes + blockSize))); bytes += blockSize; - o += blockSize; - }); - std::for_each(ops.begin(), ops.end(), [](auto && op) { - op.get(); + offset += blockSize; }); + std::ranges::for_each(ops, &std::future<void>::get); } else { - remote->write(o, safe {s}, std::make_pair(bytes, bytes + s)); + remote->write(offset, safe {size}, std::make_pair(bytes, bytes + size)); } - return safe {s}; + return safe {size}; } catch (SystemError & e) { return -e.syserrno; @@ -306,39 +302,35 @@ namespace NetFS { FuseApp::OpenFile::blockSizes(size_t total, size_t max) noexcept { if (max >= total) { // Simple case, all in remainder block - return {total, 0, 0}; + return {.size1 = total, .sizeN = 0, .count = 0}; } - else if (total % max == 0) { // Simplish case, multiples of max - return {0, max, total / max}; + if (total % max == 0) { // Simplish case, multiples of max + return {.size1 = 0, .sizeN = max, .count = total / max}; } - else { - const auto blocks = (total / max); - const auto blockSize = (total / (blocks + 1)) + 1; - const auto batchTotal = blockSize * blocks; - const auto remainder = total - batchTotal; + const auto blocks = (total / max); + const auto blockSize = (total / (blocks + 1)) + 1; + const auto batchTotal = blockSize * blocks; + const auto remainder = total - batchTotal; - return {remainder, blockSize, blocks}; - } + return {.size1 = remainder, .sizeN = blockSize, .count = blocks}; } size_t FuseApp::OpenFile::BlockSizes::total() const noexcept { - return size1 + (sizeN * N); + return size1 + (sizeN * count); } 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) + FuseApp::copy_file_range(const char *, struct fuse_file_info * fileInfoIn, off_t offsetIn, const char *, + struct fuse_file_info * fileInfoOut, off_t offsetOut, 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, safe {size}, flags); + auto openFileIn = getProxy<OpenFilePtr>(fileInfoIn->fh); + auto openFileOut = getProxy<OpenFilePtr>(fileInfoOut->fh); + openFileIn->wait(); + openFileOut->wait(); + return openFileIn->remote->copyrange(openFileOut->remote, offsetIn, offsetOut, safe {size}, flags); } catch (SystemError & e) { return -e.syserrno; @@ -346,17 +338,16 @@ namespace NetFS { } int - FuseApp::truncate(const char * p, off_t o, fuse_file_info * fi) + FuseApp::truncate(const char * path, off_t offset, fuse_file_info * fileInfo) { try { - if (fi) { - auto of = getProxy<OpenFilePtr>(fi->fh); - of->wait(); - auto remote = of->remote; - remote->ftruncate(o); + if (fileInfo) { + auto openFile = getProxy<OpenFilePtr>(fileInfo->fh); + openFile->wait(); + openFile->remote->ftruncate(offset); } else { - volume->truncate(reqEnv(), p, o); + volume->truncate(reqEnv(), path, offset); } return 0; } @@ -366,24 +357,23 @@ namespace NetFS { } int - FuseApp::getattr(const char * p, struct stat * s, fuse_file_info * fi) + FuseApp::getattr(const char * path, struct stat * stat, fuse_file_info * fileInfo) { try { - if (fi) { - auto of = getProxy<OpenFilePtr>(fi->fh); - of->wait(); - auto remote = of->remote; - *s = converter.convert(remote->fgetattr()); + if (fileInfo) { + auto openFile = getProxy<OpenFilePtr>(fileInfo->fh); + openFile->wait(); + *stat = converter.convert(openFile->remote->fgetattr()); } else { - if (auto cacehedStat = statCache.get(std::filesystem::hash_value(p))) { - *s = *cacehedStat; + if (auto cacehedStat = statCache.get(std::filesystem::hash_value(path))) { + *stat = *cacehedStat; } else { - *s = converter.convert(volume->getattr(reqEnv(), p)); + *stat = converter.convert(volume->getattr(reqEnv(), path)); } } - return s->st_mode ? 0 : -ENOENT; + return stat->st_mode ? 0 : -ENOENT; } catch (SystemError & e) { return -e.syserrno; @@ -391,10 +381,10 @@ namespace NetFS { } int - FuseApp::unlink(const char * p) + FuseApp::unlink(const char * path) { try { - volume->unlink(reqEnv(), p); + volume->unlink(reqEnv(), path); return 0; } catch (SystemError & e) { |