return;
}
+ // convert the image-extent extent map to object-extents
+ ExtentMap image_extent_map;
+ image_extent_map.swap(m_copyup_extent_map);
+ for (auto [image_offset, image_length] : image_extent_map) {
+ striper::LightweightObjectExtents object_extents;
+ Striper::file_to_extents(
+ cct, &m_image_ctx->layout, image_offset, image_length, 0, 0,
+ &object_extents);
+ for (auto& object_extent : object_extents) {
+ m_copyup_extent_map[object_extent.offset] = object_extent.length;
+ }
+ }
+
// copyup() will affect snapshots only if parent data is not all
// zeros.
if (!m_copyup_is_zero) {
return r;
}
- uint64_t buffer_length = 0;
- auto &image_extents = this->m_image_extents;
- for (auto &image_extent : image_extents) {
- buffer_length += image_extent.second;
- }
- this->m_aio_comp->read_result.set_clip_length(buffer_length);
return 0;
}
buffer_ofs += extent.second;
}
- // issue the requests
AioCompletion *aio_comp = this->m_aio_comp;
+ aio_comp->read_result.set_clip_length(buffer_ofs);
+ aio_comp->read_result.set_image_extents(image_extents);
+
+ // issue the requests
aio_comp->set_request_count(object_extents.size());
for (auto &oe : object_extents) {
ldout(cct, 20) << data_object_name(&image_ctx, oe.object_no) << " "
}
};
+struct ReadResult::SetImageExtentsVisitor : public boost::static_visitor<void> {
+ Extents image_extents;
+
+ explicit SetImageExtentsVisitor(const Extents& image_extents)
+ : image_extents(image_extents) {
+ }
+
+ void operator()(SparseBufferlist &sbl) const {
+ sbl.image_extents = image_extents;
+ }
+
+ template <typename T>
+ void operator()(T &t) const {
+ }
+};
+
struct ReadResult::AssembleResultVisitor : public boost::static_visitor<void> {
CephContext *cct;
Striper::StripedReadResult &destriper;
void operator()(SparseBufferlist &sparse_bufferlist) const {
sparse_bufferlist.extent_map->clear();
sparse_bufferlist.bl->clear();
- destriper.assemble_result(cct, sparse_bufferlist.extent_map,
- sparse_bufferlist.bl);
+ auto buffer_extents_length = destriper.assemble_result(
+ cct, sparse_bufferlist.extent_map, sparse_bufferlist.bl);
+
+ ExtentMap buffer_extent_map;
+ buffer_extent_map.swap(*sparse_bufferlist.extent_map);
+ ldout(cct, 20) << "image_extents="
+ << sparse_bufferlist.image_extents << ", "
+ << "buffer_extent_map=" << buffer_extent_map << dendl;
+
+ // 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)[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->size()
+ ldout(cct, 20) << "moved resulting " << *sparse_bufferlist.extent_map
<< " extents of total " << sparse_bufferlist.bl->length()
<< " bytes to bl "
<< reinterpret_cast<void*>(sparse_bufferlist.bl) << dendl;
boost::apply_visitor(SetClipLengthVisitor(length), m_buffer);
}
+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);
}
ReadResult(std::map<uint64_t, uint64_t> *extent_map, ceph::bufferlist *bl);
void set_clip_length(size_t length);
+ void set_image_extents(const Extents& image_extents);
+
void assemble_result(CephContext *cct);
private:
std::map<uint64_t, uint64_t> *extent_map;
ceph::bufferlist *bl;
+ Extents image_extents;
+
SparseBufferlist(std::map<uint64_t, uint64_t> *extent_map,
ceph::bufferlist *bl)
: extent_map(extent_map), bl(bl) {
Bufferlist,
SparseBufferlist> Buffer;
struct SetClipLengthVisitor;
+ struct SetImageExtentsVisitor;
struct AssembleResultVisitor;
Buffer m_buffer;