From f8914a677c44d019722472b15663ea2a199e3566 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Wed, 20 Mar 2024 20:53:02 +0000 Subject: [PATCH] osd: minimize alignment requirements of ReadPipeline Before it was operating on stripe-aligned requests, now chunk- alignment is enough. Signed-off-by: Radoslaw Zarzynski --- src/osd/ECBackend.cc | 2 +- src/osd/ECCommon.cc | 9 ++++----- src/osd/ECUtil.cc | 12 +++--------- src/osd/ECUtil.h | 16 +++++++++++++++- src/test/osd/TestECBackend.cc | 15 ++++++++++++++- 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/osd/ECBackend.cc b/src/osd/ECBackend.cc index 46e57a25951e4..2bfdda38530eb 100644 --- a/src/osd/ECBackend.cc +++ b/src/osd/ECBackend.cc @@ -1235,7 +1235,7 @@ void ECBackend::handle_sub_read_reply( ceph_assert(req_iter != rop.to_read.find(i->first)->second.to_read.end()); ceph_assert(riter != rop.complete[i->first].returned.end()); pair aligned = - sinfo.aligned_offset_len_to_chunk( + sinfo.chunk_aligned_offset_len_to_chunk( make_pair(req_iter->offset, req_iter->size)); ceph_assert(aligned.first == j->first); riter->get<2>()[from] = std::move(j->second); diff --git a/src/osd/ECCommon.cc b/src/osd/ECCommon.cc index 3f2ae7601207d..93cca1763d99d 100644 --- a/src/osd/ECCommon.cc +++ b/src/osd/ECCommon.cc @@ -439,11 +439,7 @@ void ECCommon::ReadPipeline::do_read_op(ReadOp &op) } for (const auto& read : i->second.to_read) { auto p = make_pair(read.offset, read.size); - if (g_conf()->osd_ec_partial_reads) { - // we need to align to stripe again to deal with partial chunk read. - p = sinfo.offset_len_to_stripe_bounds(p); - } - pair chunk_off_len = sinfo.aligned_offset_len_to_chunk(p); + pair chunk_off_len = sinfo.chunk_aligned_offset_len_to_chunk(p); for (auto k = i->second.need.begin(); k != i->second.need.end(); ++k) { @@ -518,6 +514,9 @@ struct ClientReadCompleter : ECCommon::ReadCompleter { ceph_assert(res.errors.empty()); for (auto &&read: to_read) { const auto bounds = make_pair(read.offset, read.size); + // the configurable serves only the preservation of old behavior + // which will be dropped. ReadPipeline is actually able to handle + // reads aligned to chunk size. const auto aligned = g_conf()->osd_ec_partial_reads \ ? read_pipeline.sinfo.offset_len_to_chunk_bounds(bounds) : read_pipeline.sinfo.offset_len_to_stripe_bounds(bounds); diff --git a/src/osd/ECUtil.cc b/src/osd/ECUtil.cc index 44e3665844931..6d9477a99af78 100644 --- a/src/osd/ECUtil.cc +++ b/src/osd/ECUtil.cc @@ -11,14 +11,11 @@ using ceph::bufferlist; using ceph::ErasureCodeInterfaceRef; using ceph::Formatter; -std::pair ECUtil::stripe_info_t::aligned_offset_len_to_chunk( +std::pair ECUtil::stripe_info_t::chunk_aligned_offset_len_to_chunk( std::pair in) const { - // we need to align to stripe again to deal with partial chunk read. - auto aligned = - g_conf()->osd_ec_partial_reads ? offset_len_to_stripe_bounds(in) : in; return std::make_pair( - aligned_logical_offset_to_chunk_offset(aligned.first), - aligned_logical_offset_to_chunk_offset(aligned.second)); + chunk_aligned_logical_offset_to_chunk_offset(in.first), + chunk_aligned_logical_size_to_chunk_size(in.second)); } int ECUtil::decode( @@ -56,9 +53,6 @@ int ECUtil::decode( int r = ec_impl->decode_concat(want_to_read, chunks, &bl); ceph_assert(r == 0); ceph_assert(bl.length() % sinfo.get_chunk_size() == 0); - if (!g_conf()->osd_ec_partial_reads) { - ceph_assert(bl.length() == sinfo.get_stripe_width()); - } out->claim_append(bl); } return 0; diff --git a/src/osd/ECUtil.h b/src/osd/ECUtil.h index a835ec3226476..af21839da23eb 100644 --- a/src/osd/ECUtil.h +++ b/src/osd/ECUtil.h @@ -63,11 +63,25 @@ public: ceph_assert(offset % stripe_width == 0); return (offset / stripe_width) * chunk_size; } + uint64_t chunk_aligned_logical_offset_to_chunk_offset(uint64_t offset) const { + [[maybe_unused]] const auto residue_in_stripe = offset % stripe_width; + ceph_assert(residue_in_stripe % chunk_size == 0); + ceph_assert(stripe_width % chunk_size == 0); + // this rounds down + return (offset / stripe_width) * chunk_size; + } + uint64_t chunk_aligned_logical_size_to_chunk_size(uint64_t len) const { + [[maybe_unused]] const auto residue_in_stripe = len % stripe_width; + ceph_assert(residue_in_stripe % chunk_size == 0); + ceph_assert(stripe_width % chunk_size == 0); + // this rounds up + return ((len + stripe_width - 1) / stripe_width) * chunk_size; + } uint64_t aligned_chunk_offset_to_logical_offset(uint64_t offset) const { ceph_assert(offset % chunk_size == 0); return (offset / chunk_size) * stripe_width; } - std::pair aligned_offset_len_to_chunk( + std::pair chunk_aligned_offset_len_to_chunk( std::pair in) const; std::pair offset_len_to_stripe_bounds( std::pair in) const { diff --git a/src/test/osd/TestECBackend.cc b/src/test/osd/TestECBackend.cc index 1c13fb4c95c01..08e94bcb6fa11 100644 --- a/src/test/osd/TestECBackend.cc +++ b/src/test/osd/TestECBackend.cc @@ -53,9 +53,22 @@ TEST(ECUtil, stripe_info_t) ASSERT_EQ(s.aligned_chunk_offset_to_logical_offset(2*s.get_chunk_size()), 2*s.get_stripe_width()); - ASSERT_EQ(s.aligned_offset_len_to_chunk(make_pair(swidth, 10*swidth)), + ASSERT_EQ(s.chunk_aligned_offset_len_to_chunk( + make_pair(swidth+s.get_chunk_size(), 10*swidth)), make_pair(s.get_chunk_size(), 10*s.get_chunk_size())); + ASSERT_EQ(s.chunk_aligned_offset_len_to_chunk(make_pair(swidth, 10*swidth)), + make_pair(s.get_chunk_size(), 10*s.get_chunk_size())); + + // round down offset if it's under stripe width + ASSERT_EQ(s.chunk_aligned_offset_len_to_chunk(make_pair(s.get_chunk_size(), 10*swidth)), + make_pair(0, 10*s.get_chunk_size())); + + // round up size if above stripe + ASSERT_EQ(s.chunk_aligned_offset_len_to_chunk(make_pair(s.get_chunk_size(), + 10*swidth + s.get_chunk_size())), + make_pair(0, 11*s.get_chunk_size())); + ASSERT_EQ(s.offset_len_to_stripe_bounds(make_pair(swidth-10, (uint64_t)20)), make_pair((uint64_t)0, 2*swidth)); } -- 2.39.5