From d0c560917293681978dc2eef28c6fe1349e10e50 Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Mon, 19 Aug 2024 10:44:44 +0200 Subject: [PATCH] feat(filesystem_v2): support maxiov parameter for readv() --- include/dwarfs/reader/filesystem_v2.h | 32 +++++++ .../dwarfs/reader/internal/inode_reader_v2.h | 16 ++-- src/reader/filesystem_v2.cpp | 91 +++++++++++++++---- src/reader/internal/inode_reader_v2.cpp | 40 ++++---- 4 files changed, 133 insertions(+), 46 deletions(-) diff --git a/include/dwarfs/reader/filesystem_v2.h b/include/dwarfs/reader/filesystem_v2.h index 9ba7738c..cb401985 100644 --- a/include/dwarfs/reader/filesystem_v2.h +++ b/include/dwarfs/reader/filesystem_v2.h @@ -245,6 +245,11 @@ class filesystem_v2 { return impl_->readv(inode, buf, size, offset, ec); } + size_t readv(uint32_t inode, iovec_read_buf& buf, size_t size, + file_off_t offset, size_t maxiov, std::error_code& ec) const { + return impl_->readv(inode, buf, size, offset, maxiov, ec); + } + size_t readv(uint32_t inode, iovec_read_buf& buf, size_t size, std::error_code& ec) const { return impl_->readv(inode, buf, size, 0, ec); @@ -255,6 +260,11 @@ class filesystem_v2 { return impl_->readv(inode, buf, size, offset); } + size_t readv(uint32_t inode, iovec_read_buf& buf, size_t size, + file_off_t offset, size_t maxiov) const { + return impl_->readv(inode, buf, size, offset, maxiov); + } + std::vector> readv(uint32_t inode) const { return impl_->readv(inode); } @@ -269,6 +279,11 @@ class filesystem_v2 { return impl_->readv(inode, size, offset); } + std::vector> + readv(uint32_t inode, size_t size, file_off_t offset, size_t maxiov) const { + return impl_->readv(inode, size, offset, maxiov); + } + std::vector> readv(uint32_t inode, size_t size, std::error_code& ec) const { return impl_->readv(inode, size, 0, ec); @@ -280,6 +295,12 @@ class filesystem_v2 { return impl_->readv(inode, size, offset, ec); } + std::vector> + readv(uint32_t inode, size_t size, file_off_t offset, size_t maxiov, + std::error_code& ec) const { + return impl_->readv(inode, size, offset, maxiov, ec); + } + std::optional> header() const { return impl_->header(); } @@ -378,6 +399,11 @@ class filesystem_v2 { file_off_t offset, std::error_code& ec) const = 0; virtual size_t readv(uint32_t inode, iovec_read_buf& buf, size_t size, file_off_t offset) const = 0; + virtual size_t + readv(uint32_t inode, iovec_read_buf& buf, size_t size, file_off_t offset, + size_t maxiov, std::error_code& ec) const = 0; + virtual size_t readv(uint32_t inode, iovec_read_buf& buf, size_t size, + file_off_t offset, size_t maxiov) const = 0; virtual std::vector> readv(uint32_t inode) const = 0; virtual std::vector> @@ -387,6 +413,12 @@ class filesystem_v2 { virtual std::vector> readv(uint32_t inode, size_t size, file_off_t offset, std::error_code& ec) const = 0; + virtual std::vector> + readv(uint32_t inode, size_t size, file_off_t offset, + size_t maxiov) const = 0; + virtual std::vector> + readv(uint32_t inode, size_t size, file_off_t offset, size_t maxiov, + std::error_code& ec) const = 0; virtual std::optional> header() const = 0; virtual void set_num_workers(size_t num) = 0; virtual void set_cache_tidy_config(cache_tidy_config const& cfg) = 0; diff --git a/include/dwarfs/reader/internal/inode_reader_v2.h b/include/dwarfs/reader/internal/inode_reader_v2.h index 5454a707..e61d786d 100644 --- a/include/dwarfs/reader/internal/inode_reader_v2.h +++ b/include/dwarfs/reader/internal/inode_reader_v2.h @@ -66,14 +66,14 @@ class inode_reader_v2 { size_t readv(iovec_read_buf& buf, uint32_t inode, size_t size, file_off_t offset, - chunk_range chunks, std::error_code& ec) const { - return impl_->readv(buf, inode, size, offset, chunks, ec); + size_t maxiov, chunk_range chunks, std::error_code& ec) const { + return impl_->readv(buf, inode, size, offset, maxiov, chunks, ec); } std::vector> - readv(uint32_t inode, size_t size, file_off_t offset, chunk_range chunks, - std::error_code& ec) const { - return impl_->readv(inode, size, offset, chunks, ec); + readv(uint32_t inode, size_t size, file_off_t offset, size_t maxiov, + chunk_range chunks, std::error_code& ec) const { + return impl_->readv(inode, size, offset, maxiov, chunks, ec); } void @@ -101,10 +101,10 @@ class inode_reader_v2 { chunk_range chunks, std::error_code& ec) const = 0; virtual size_t readv(iovec_read_buf& buf, uint32_t inode, size_t size, file_off_t offset, - chunk_range chunks, std::error_code& ec) const = 0; + size_t maxiov, chunk_range chunks, std::error_code& ec) const = 0; virtual std::vector> - readv(uint32_t inode, size_t size, file_off_t offset, chunk_range chunks, - std::error_code& ec) const = 0; + readv(uint32_t inode, size_t size, file_off_t offset, size_t maxiov, + chunk_range chunks, std::error_code& ec) const = 0; virtual void dump(std::ostream& os, const std::string& indent, chunk_range chunks) const = 0; virtual void set_num_workers(size_t num) = 0; diff --git a/src/reader/filesystem_v2.cpp b/src/reader/filesystem_v2.cpp index 4a174a46..ae816b94 100644 --- a/src/reader/filesystem_v2.cpp +++ b/src/reader/filesystem_v2.cpp @@ -62,6 +62,9 @@ using namespace dwarfs::internal; namespace { +constexpr size_t const kDefaultMaxIOV{std::numeric_limits::max()}; +constexpr size_t const KReadFullFile{std::numeric_limits::max()}; + void check_section_logger(logger& lgr, fs_section const& section) { LOG_PROXY(debug_logger_policy, lgr); @@ -259,6 +262,11 @@ class filesystem_ final : public filesystem_v2::impl { file_off_t offset, std::error_code& ec) const override; size_t readv(uint32_t inode, iovec_read_buf& buf, size_t size, file_off_t offset) const override; + size_t + readv(uint32_t inode, iovec_read_buf& buf, size_t size, file_off_t offset, + size_t maxiov, std::error_code& ec) const override; + size_t readv(uint32_t inode, iovec_read_buf& buf, size_t size, + file_off_t offset, size_t maxiov) const override; std::vector> readv(uint32_t inode) const override; std::vector> readv(uint32_t inode, std::error_code& ec) const override; @@ -267,6 +275,12 @@ class filesystem_ final : public filesystem_v2::impl { std::vector> readv(uint32_t inode, size_t size, file_off_t offset, std::error_code& ec) const override; + std::vector> + readv(uint32_t inode, size_t size, file_off_t offset, + size_t maxiov) const override; + std::vector> + readv(uint32_t inode, size_t size, file_off_t offset, size_t maxiov, + std::error_code& ec) const override; std::optional> header() const override; void set_num_workers(size_t num) override { ir_.set_num_workers(num); } void set_cache_tidy_config(cache_tidy_config const& cfg) override { @@ -303,9 +317,9 @@ class filesystem_ final : public filesystem_v2::impl { size_t read_ec(uint32_t inode, char* buf, size_t size, file_off_t offset, std::error_code& ec) const; size_t readv_ec(uint32_t inode, iovec_read_buf& buf, size_t size, - file_off_t offset, std::error_code& ec) const; + file_off_t offset, size_t maxiov, std::error_code& ec) const; std::vector> - readv_ec(uint32_t inode, size_t size, file_off_t offset, + readv_ec(uint32_t inode, size_t size, file_off_t offset, size_t maxiov, std::error_code& ec) const; LOG_PROXY_DECL(LoggerPolicy); @@ -859,14 +873,14 @@ template std::string filesystem_::read_string(uint32_t inode, std::error_code& ec) const { PERFMON_CLS_SCOPED_SECTION(read_string_ec) - return read_string_ec(inode, std::numeric_limits::max(), 0, ec); + return read_string_ec(inode, KReadFullFile, 0, ec); } template std::string filesystem_::read_string(uint32_t inode) const { PERFMON_CLS_SCOPED_SECTION(read_string) return call_ec_throw([&](std::error_code& ec) { - return read_string_ec(inode, std::numeric_limits::max(), 0, ec); + return read_string_ec(inode, KReadFullFile, 0, ec); }); } @@ -916,12 +930,13 @@ size_t filesystem_::read(uint32_t inode, char* buf, size_t size, } template -size_t filesystem_::readv_ec(uint32_t inode, iovec_read_buf& buf, - size_t size, file_off_t offset, - std::error_code& ec) const { +size_t +filesystem_::readv_ec(uint32_t inode, iovec_read_buf& buf, + size_t size, file_off_t offset, + size_t maxiov, std::error_code& ec) const { auto chunks = meta_.get_chunks(inode, ec); if (!ec) { - return ir_.readv(buf, inode, size, offset, chunks, ec); + return ir_.readv(buf, inode, size, offset, maxiov, chunks, ec); } return 0; } @@ -930,7 +945,7 @@ template size_t filesystem_::readv(uint32_t inode, iovec_read_buf& buf, std::error_code& ec) const { PERFMON_CLS_SCOPED_SECTION(readv_iovec_ec) - return readv_ec(inode, buf, std::numeric_limits::max(), 0, ec); + return readv_ec(inode, buf, KReadFullFile, 0, kDefaultMaxIOV, ec); } template @@ -938,7 +953,7 @@ size_t filesystem_::readv(uint32_t inode, iovec_read_buf& buf) const { PERFMON_CLS_SCOPED_SECTION(readv_iovec) return call_ec_throw([&](std::error_code& ec) { - return readv_ec(inode, buf, std::numeric_limits::max(), 0, ec); + return readv_ec(inode, buf, KReadFullFile, 0, kDefaultMaxIOV, ec); }); } @@ -947,7 +962,7 @@ size_t filesystem_::readv(uint32_t inode, iovec_read_buf& buf, size_t size, file_off_t offset, std::error_code& ec) const { PERFMON_CLS_SCOPED_SECTION(readv_iovec_ec) - return readv_ec(inode, buf, size, offset, ec); + return readv_ec(inode, buf, size, offset, kDefaultMaxIOV, ec); } template @@ -955,18 +970,37 @@ size_t filesystem_::readv(uint32_t inode, iovec_read_buf& buf, size_t size, file_off_t offset) const { PERFMON_CLS_SCOPED_SECTION(readv_iovec) return call_ec_throw([&](std::error_code& ec) { - return readv_ec(inode, buf, size, offset, ec); + return readv_ec(inode, buf, size, offset, kDefaultMaxIOV, ec); + }); +} + +template +size_t +filesystem_::readv(uint32_t inode, iovec_read_buf& buf, + size_t size, file_off_t offset, size_t maxiov, + std::error_code& ec) const { + PERFMON_CLS_SCOPED_SECTION(readv_iovec_ec) + return readv_ec(inode, buf, size, offset, maxiov, ec); +} + +template +size_t filesystem_::readv(uint32_t inode, iovec_read_buf& buf, + size_t size, file_off_t offset, + size_t maxiov) const { + PERFMON_CLS_SCOPED_SECTION(readv_iovec) + return call_ec_throw([&](std::error_code& ec) { + return readv_ec(inode, buf, size, offset, maxiov, ec); }); } template std::vector> filesystem_::readv_ec(uint32_t inode, size_t size, - file_off_t offset, + file_off_t offset, size_t maxiov, std::error_code& ec) const { auto chunks = meta_.get_chunks(inode, ec); if (!ec) { - return ir_.readv(inode, size, offset, chunks, ec); + return ir_.readv(inode, size, offset, maxiov, chunks, ec); } return {}; } @@ -975,7 +1009,7 @@ template std::vector> filesystem_::readv(uint32_t inode, std::error_code& ec) const { PERFMON_CLS_SCOPED_SECTION(readv_future_ec) - return readv_ec(inode, std::numeric_limits::max(), 0, ec); + return readv_ec(inode, KReadFullFile, 0, kDefaultMaxIOV, ec); } template @@ -983,7 +1017,7 @@ std::vector> filesystem_::readv(uint32_t inode) const { PERFMON_CLS_SCOPED_SECTION(readv_future) return call_ec_throw([&](std::error_code& ec) { - return readv_ec(inode, std::numeric_limits::max(), 0, ec); + return readv_ec(inode, KReadFullFile, 0, kDefaultMaxIOV, ec); }); } @@ -992,7 +1026,7 @@ std::vector> filesystem_::readv(uint32_t inode, size_t size, file_off_t offset, std::error_code& ec) const { PERFMON_CLS_SCOPED_SECTION(readv_future_ec) - return readv_ec(inode, size, offset, ec); + return readv_ec(inode, size, offset, kDefaultMaxIOV, ec); } template @@ -1000,8 +1034,27 @@ std::vector> filesystem_::readv(uint32_t inode, size_t size, file_off_t offset) const { PERFMON_CLS_SCOPED_SECTION(readv_future) - return call_ec_throw( - [&](std::error_code& ec) { return readv_ec(inode, size, offset, ec); }); + return call_ec_throw([&](std::error_code& ec) { + return readv_ec(inode, size, offset, kDefaultMaxIOV, ec); + }); +} + +template +std::vector> +filesystem_::readv(uint32_t inode, size_t size, file_off_t offset, + size_t maxiov, std::error_code& ec) const { + PERFMON_CLS_SCOPED_SECTION(readv_future_ec) + return readv_ec(inode, size, offset, maxiov, ec); +} + +template +std::vector> +filesystem_::readv(uint32_t inode, size_t size, file_off_t offset, + size_t maxiov) const { + PERFMON_CLS_SCOPED_SECTION(readv_future) + return call_ec_throw([&](std::error_code& ec) { + return readv_ec(inode, size, offset, maxiov, ec); + }); } template diff --git a/src/reader/internal/inode_reader_v2.cpp b/src/reader/internal/inode_reader_v2.cpp index 07fea889..67a265ec 100644 --- a/src/reader/internal/inode_reader_v2.cpp +++ b/src/reader/internal/inode_reader_v2.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,8 @@ namespace dwarfs::reader::internal { namespace { +constexpr size_t const kReadAllIOV{std::numeric_limits::max()}; + /** * Offset cache configuration * @@ -130,10 +133,10 @@ class inode_reader_ final : public inode_reader_v2::impl { chunk_range chunks, std::error_code& ec) const override; size_t readv(iovec_read_buf& buf, uint32_t inode, size_t size, file_off_t offset, - chunk_range chunks, std::error_code& ec) const override; + size_t maxiov, chunk_range chunks, std::error_code& ec) const override; std::vector> - readv(uint32_t inode, size_t size, file_off_t offset, chunk_range chunks, - std::error_code& ec) const override; + readv(uint32_t inode, size_t size, file_off_t offset, size_t maxiov, + chunk_range chunks, std::error_code& ec) const override; void dump(std::ostream& os, const std::string& indent, chunk_range chunks) const override; void set_num_workers(size_t num) override { cache_.set_num_workers(num); } @@ -151,12 +154,12 @@ class inode_reader_ final : public inode_reader_v2::impl { using readahead_cache_type = folly::EvictingCacheMap; std::vector> - read_internal(uint32_t inode, size_t size, file_off_t offset, + read_internal(uint32_t inode, size_t size, file_off_t offset, size_t maxiov, chunk_range chunks, std::error_code& ec) const; template size_t read_internal(uint32_t inode, size_t size, file_off_t read_offset, - chunk_range chunks, std::error_code& ec, + size_t maxiov, chunk_range chunks, std::error_code& ec, const StoreFunc& store) const; void do_readahead(uint32_t inode, chunk_range::iterator it, @@ -237,6 +240,7 @@ template std::vector> inode_reader_::read_internal(uint32_t inode, size_t const size, file_off_t const read_offset, + size_t const maxiov, chunk_range chunks, std::error_code& ec) const { std::vector> ranges; @@ -315,7 +319,7 @@ inode_reader_::read_internal(uint32_t inode, size_t const size, num_read += copysize; - if (num_read == size) { + if (num_read == size || ranges.size() >= maxiov) { if (oc_ent) { oc_ent->update(oc_upd, it_index, it_offset, chunksize); offset_cache_.set(inode, std::move(oc_ent)); @@ -340,13 +344,10 @@ inode_reader_::read_internal(uint32_t inode, size_t const size, template template -size_t -inode_reader_::read_internal(uint32_t inode, size_t size, - file_off_t offset, - chunk_range chunks, - std::error_code& ec, - const StoreFunc& store) const { - auto ranges = read_internal(inode, size, offset, chunks, ec); +size_t inode_reader_::read_internal( + uint32_t inode, size_t size, file_off_t offset, size_t const maxiov, + chunk_range chunks, std::error_code& ec, const StoreFunc& store) const { + auto ranges = read_internal(inode, size, offset, maxiov, chunks, ec); if (ec) { return 0; @@ -378,7 +379,7 @@ inode_reader_::read_string(uint32_t inode, size_t size, PERFMON_CLS_SCOPED_SECTION(read_string) PERFMON_SET_CONTEXT(static_cast(offset), size); - auto ranges = read_internal(inode, size, offset, chunks, ec); + auto ranges = read_internal(inode, size, offset, kReadAllIOV, chunks, ec); std::string res; @@ -411,7 +412,7 @@ size_t inode_reader_::read(char* buf, uint32_t inode, size_t size, PERFMON_CLS_SCOPED_SECTION(read) PERFMON_SET_CONTEXT(static_cast(offset), size); - return read_internal(inode, size, offset, chunks, ec, + return read_internal(inode, size, offset, kReadAllIOV, chunks, ec, [&](size_t num_read, const block_range& br) { ::memcpy(buf + num_read, br.data(), br.size()); }); @@ -420,23 +421,24 @@ size_t inode_reader_::read(char* buf, uint32_t inode, size_t size, template std::vector> inode_reader_::readv(uint32_t inode, size_t const size, - file_off_t offset, chunk_range chunks, + file_off_t offset, size_t maxiov, + chunk_range chunks, std::error_code& ec) const { PERFMON_CLS_SCOPED_SECTION(readv_future) PERFMON_SET_CONTEXT(static_cast(offset), size); - return read_internal(inode, size, offset, chunks, ec); + return read_internal(inode, size, offset, maxiov, chunks, ec); } template size_t inode_reader_::readv(iovec_read_buf& buf, uint32_t inode, size_t size, file_off_t offset, - chunk_range chunks, + size_t maxiov, chunk_range chunks, std::error_code& ec) const { PERFMON_CLS_SCOPED_SECTION(readv_iovec) PERFMON_SET_CONTEXT(static_cast(offset), size); - auto rv = read_internal(inode, size, offset, chunks, ec, + auto rv = read_internal(inode, size, offset, maxiov, chunks, ec, [&](size_t, const block_range& br) { auto& iov = buf.buf.emplace_back(); iov.iov_base = const_cast(br.data());