From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:54:28 +0200 Subject: Adding upstream version 18.2.2. Signed-off-by: Daniel Baumann --- src/librbd/io/ReadResult.cc | 262 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 src/librbd/io/ReadResult.cc (limited to 'src/librbd/io/ReadResult.cc') diff --git a/src/librbd/io/ReadResult.cc b/src/librbd/io/ReadResult.cc new file mode 100644 index 000000000..c4053fee6 --- /dev/null +++ b/src/librbd/io/ReadResult.cc @@ -0,0 +1,262 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/io/ReadResult.h" +#include "include/buffer.h" +#include "common/dout.h" +#include "librbd/io/AioCompletion.h" +#include "librbd/io/Utils.h" +#include +#include + +#define dout_subsys ceph_subsys_rbd +#undef dout_prefix +#define dout_prefix *_dout << "librbd::io::ReadResult: " << this \ + << " " << __func__ << ": " + +namespace librbd { +namespace io { + +struct ReadResult::SetImageExtentsVisitor : public boost::static_visitor { + Extents image_extents; + + explicit SetImageExtentsVisitor(const Extents& image_extents) + : image_extents(image_extents) { + } + + void operator()(Linear &linear) const { + uint64_t length = util::get_extents_length(image_extents); + + ceph_assert(length <= linear.buf_len); + linear.buf_len = length; + } + + void operator()(SparseBufferlist &sbl) const { + sbl.image_extents = image_extents; + } + + template + void operator()(T &t) const { + } +}; + +struct ReadResult::AssembleResultVisitor : public boost::static_visitor { + CephContext *cct; + Striper::StripedReadResult &destriper; + + AssembleResultVisitor(CephContext *cct, Striper::StripedReadResult &destriper) + : cct(cct), destriper(destriper) { + } + + void operator()(Empty &empty) const { + ldout(cct, 20) << "dropping read result" << dendl; + } + + void operator()(Linear &linear) const { + ldout(cct, 20) << "copying resulting bytes to " + << reinterpret_cast(linear.buf) << dendl; + destriper.assemble_result(cct, linear.buf, linear.buf_len); + } + + void operator()(Vector &vector) const { + bufferlist bl; + destriper.assemble_result(cct, bl, true); + + ldout(cct, 20) << "copying resulting " << bl.length() << " bytes to iovec " + << reinterpret_cast(vector.iov) << dendl; + + bufferlist::iterator it = bl.begin(); + size_t length = bl.length(); + size_t offset = 0; + int idx = 0; + for (; offset < length && idx < vector.iov_count; idx++) { + size_t len = std::min(vector.iov[idx].iov_len, length - offset); + it.copy(len, static_cast(vector.iov[idx].iov_base)); + offset += len; + } + ceph_assert(offset == bl.length()); + } + + void operator()(Bufferlist &bufferlist) const { + bufferlist.bl->clear(); + destriper.assemble_result(cct, *bufferlist.bl, true); + + ldout(cct, 20) << "moved resulting " << bufferlist.bl->length() << " " + << "bytes to bl " << reinterpret_cast(bufferlist.bl) + << dendl; + } + + void operator()(SparseBufferlist &sparse_bufferlist) const { + sparse_bufferlist.bl->clear(); + + ExtentMap buffer_extent_map; + auto buffer_extents_length = destriper.assemble_result( + cct, &buffer_extent_map, sparse_bufferlist.bl); + + ldout(cct, 20) << "image_extents=" + << sparse_bufferlist.image_extents << ", " + << "buffer_extent_map=" << buffer_extent_map << dendl; + + sparse_bufferlist.extent_map->clear(); + sparse_bufferlist.extent_map->reserve(buffer_extent_map.size()); + + // The extent-map is logically addressed by buffer-extents not image- or + // object-extents. Translate this address mapping to image-extent + // logical addressing since it's tied to an image-extent read + uint64_t buffer_offset = 0; + auto bem_it = buffer_extent_map.begin(); + for (auto [image_offset, image_length] : sparse_bufferlist.image_extents) { + while (bem_it != buffer_extent_map.end()) { + auto [buffer_extent_offset, buffer_extent_length] = *bem_it; + + if (buffer_offset + image_length <= buffer_extent_offset) { + // skip any image extent that is not included in the results + break; + } + + // current buffer-extent should be within the current image-extent + ceph_assert(buffer_offset <= buffer_extent_offset && + buffer_offset + image_length >= + buffer_extent_offset + buffer_extent_length); + auto image_extent_offset = + image_offset + (buffer_extent_offset - buffer_offset); + ldout(cct, 20) << "mapping buffer extent " << buffer_extent_offset + << "~" << buffer_extent_length << " to image extent " + << image_extent_offset << "~" << buffer_extent_length + << dendl; + sparse_bufferlist.extent_map->emplace_back( + image_extent_offset, buffer_extent_length); + ++bem_it; + } + + buffer_offset += image_length; + } + ceph_assert(buffer_offset == buffer_extents_length); + ceph_assert(bem_it == buffer_extent_map.end()); + + ldout(cct, 20) << "moved resulting " << *sparse_bufferlist.extent_map + << " extents of total " << sparse_bufferlist.bl->length() + << " bytes to bl " + << reinterpret_cast(sparse_bufferlist.bl) << dendl; + } +}; + +ReadResult::C_ImageReadRequest::C_ImageReadRequest( + AioCompletion *aio_completion, uint64_t buffer_offset, + const Extents image_extents) + : aio_completion(aio_completion), buffer_offset(buffer_offset), + image_extents(image_extents) { + aio_completion->add_request(); +} + +void ReadResult::C_ImageReadRequest::finish(int r) { + CephContext *cct = aio_completion->ictx->cct; + ldout(cct, 10) << "C_ImageReadRequest: r=" << r + << dendl; + if (r >= 0 || (ignore_enoent && r == -ENOENT)) { + striper::LightweightBufferExtents buffer_extents; + size_t length = 0; + for (auto &image_extent : image_extents) { + buffer_extents.emplace_back(buffer_offset + length, image_extent.second); + length += image_extent.second; + } + ceph_assert(r == -ENOENT || length == bl.length()); + + aio_completion->lock.lock(); + aio_completion->read_result.m_destriper.add_partial_result( + cct, std::move(bl), buffer_extents); + aio_completion->lock.unlock(); + r = length; + } + + aio_completion->complete_request(r); +} + +ReadResult::C_ObjectReadRequest::C_ObjectReadRequest( + AioCompletion *aio_completion, ReadExtents&& extents) + : aio_completion(aio_completion), extents(std::move(extents)) { + aio_completion->add_request(); +} + +void ReadResult::C_ObjectReadRequest::finish(int r) { + CephContext *cct = aio_completion->ictx->cct; + ldout(cct, 10) << "C_ObjectReadRequest: r=" << r + << dendl; + + if (r == -ENOENT) { + r = 0; + } + if (r >= 0) { + uint64_t object_len = 0; + aio_completion->lock.lock(); + for (auto& extent: extents) { + ldout(cct, 10) << " got " << extent.extent_map + << " for " << extent.buffer_extents + << " bl " << extent.bl.length() << dendl; + + aio_completion->read_result.m_destriper.add_partial_sparse_result( + cct, std::move(extent.bl), extent.extent_map, extent.offset, + extent.buffer_extents); + + object_len += extent.length; + } + aio_completion->lock.unlock(); + r = object_len; + } + + aio_completion->complete_request(r); +} + +ReadResult::C_ObjectReadMergedExtents::C_ObjectReadMergedExtents( + CephContext* cct, ReadExtents* extents, Context* on_finish) + : cct(cct), extents(extents), on_finish(on_finish) { +} + +void ReadResult::C_ObjectReadMergedExtents::finish(int r) { + if (r >= 0) { + for (auto& extent: *extents) { + if (bl.length() < extent.length) { + lderr(cct) << "Merged extents length is less than expected" << dendl; + r = -EIO; + break; + } + bl.splice(0, extent.length, &extent.bl); + } + if (bl.length() != 0) { + lderr(cct) << "Merged extents length is greater than expected" << dendl; + r = -EIO; + } + } + on_finish->complete(r); +} + +ReadResult::ReadResult() : m_buffer(Empty()) { +} + +ReadResult::ReadResult(char *buf, size_t buf_len) + : m_buffer(Linear(buf, buf_len)) { +} + +ReadResult::ReadResult(const struct iovec *iov, int iov_count) + : m_buffer(Vector(iov, iov_count)) { +} + +ReadResult::ReadResult(ceph::bufferlist *bl) + : m_buffer(Bufferlist(bl)) { +} + +ReadResult::ReadResult(Extents* extent_map, ceph::bufferlist* bl) + : m_buffer(SparseBufferlist(extent_map, bl)) { +} + +void ReadResult::set_image_extents(const Extents& image_extents) { + boost::apply_visitor(SetImageExtentsVisitor(image_extents), m_buffer); +} + +void ReadResult::assemble_result(CephContext *cct) { + boost::apply_visitor(AssembleResultVisitor(cct, m_destriper), m_buffer); +} + +} // namespace io +} // namespace librbd + -- cgit v1.2.3