]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "librbd/io/ReadResult.h" | |
5 | #include "include/buffer.h" | |
6 | #include "common/dout.h" | |
7 | #include "librbd/io/AioCompletion.h" | |
f67539c2 | 8 | #include "librbd/io/Utils.h" |
7c673cae FG |
9 | #include <boost/variant/apply_visitor.hpp> |
10 | #include <boost/variant/static_visitor.hpp> | |
11 | ||
12 | #define dout_subsys ceph_subsys_rbd | |
13 | #undef dout_prefix | |
14 | #define dout_prefix *_dout << "librbd::io::ReadResult: " << this \ | |
15 | << " " << __func__ << ": " | |
16 | ||
17 | namespace librbd { | |
18 | namespace io { | |
19 | ||
f67539c2 TL |
20 | struct ReadResult::SetImageExtentsVisitor : public boost::static_visitor<void> { |
21 | Extents image_extents; | |
7c673cae | 22 | |
f67539c2 TL |
23 | explicit SetImageExtentsVisitor(const Extents& image_extents) |
24 | : image_extents(image_extents) { | |
7c673cae FG |
25 | } |
26 | ||
27 | void operator()(Linear &linear) const { | |
f67539c2 TL |
28 | uint64_t length = util::get_extents_length(image_extents); |
29 | ||
11fdf7f2 | 30 | ceph_assert(length <= linear.buf_len); |
7c673cae FG |
31 | linear.buf_len = length; |
32 | } | |
33 | ||
f67539c2 TL |
34 | void operator()(SparseBufferlist &sbl) const { |
35 | sbl.image_extents = image_extents; | |
36 | } | |
37 | ||
7c673cae FG |
38 | template <typename T> |
39 | void operator()(T &t) const { | |
40 | } | |
41 | }; | |
42 | ||
43 | struct ReadResult::AssembleResultVisitor : public boost::static_visitor<void> { | |
44 | CephContext *cct; | |
45 | Striper::StripedReadResult &destriper; | |
46 | ||
47 | AssembleResultVisitor(CephContext *cct, Striper::StripedReadResult &destriper) | |
48 | : cct(cct), destriper(destriper) { | |
49 | } | |
50 | ||
51 | void operator()(Empty &empty) const { | |
52 | ldout(cct, 20) << "dropping read result" << dendl; | |
53 | } | |
54 | ||
55 | void operator()(Linear &linear) const { | |
56 | ldout(cct, 20) << "copying resulting bytes to " | |
57 | << reinterpret_cast<void*>(linear.buf) << dendl; | |
58 | destriper.assemble_result(cct, linear.buf, linear.buf_len); | |
59 | } | |
60 | ||
61 | void operator()(Vector &vector) const { | |
62 | bufferlist bl; | |
63 | destriper.assemble_result(cct, bl, true); | |
64 | ||
65 | ldout(cct, 20) << "copying resulting " << bl.length() << " bytes to iovec " | |
66 | << reinterpret_cast<const void*>(vector.iov) << dendl; | |
67 | ||
68 | bufferlist::iterator it = bl.begin(); | |
69 | size_t length = bl.length(); | |
70 | size_t offset = 0; | |
71 | int idx = 0; | |
72 | for (; offset < length && idx < vector.iov_count; idx++) { | |
11fdf7f2 | 73 | size_t len = std::min(vector.iov[idx].iov_len, length - offset); |
7c673cae FG |
74 | it.copy(len, static_cast<char *>(vector.iov[idx].iov_base)); |
75 | offset += len; | |
76 | } | |
11fdf7f2 | 77 | ceph_assert(offset == bl.length()); |
7c673cae FG |
78 | } |
79 | ||
80 | void operator()(Bufferlist &bufferlist) const { | |
81 | bufferlist.bl->clear(); | |
82 | destriper.assemble_result(cct, *bufferlist.bl, true); | |
83 | ||
84 | ldout(cct, 20) << "moved resulting " << bufferlist.bl->length() << " " | |
85 | << "bytes to bl " << reinterpret_cast<void*>(bufferlist.bl) | |
86 | << dendl; | |
87 | } | |
9f95a23c TL |
88 | |
89 | void operator()(SparseBufferlist &sparse_bufferlist) const { | |
9f95a23c | 90 | sparse_bufferlist.bl->clear(); |
9f95a23c | 91 | |
f67539c2 TL |
92 | ExtentMap buffer_extent_map; |
93 | auto buffer_extents_length = destriper.assemble_result( | |
94 | cct, &buffer_extent_map, sparse_bufferlist.bl); | |
95 | ||
96 | ldout(cct, 20) << "image_extents=" | |
97 | << sparse_bufferlist.image_extents << ", " | |
98 | << "buffer_extent_map=" << buffer_extent_map << dendl; | |
99 | ||
100 | sparse_bufferlist.extent_map->clear(); | |
101 | sparse_bufferlist.extent_map->reserve(buffer_extent_map.size()); | |
102 | ||
103 | // The extent-map is logically addressed by buffer-extents not image- or | |
104 | // object-extents. Translate this address mapping to image-extent | |
105 | // logical addressing since it's tied to an image-extent read | |
106 | uint64_t buffer_offset = 0; | |
107 | auto bem_it = buffer_extent_map.begin(); | |
108 | for (auto [image_offset, image_length] : sparse_bufferlist.image_extents) { | |
109 | while (bem_it != buffer_extent_map.end()) { | |
110 | auto [buffer_extent_offset, buffer_extent_length] = *bem_it; | |
111 | ||
112 | if (buffer_offset + image_length <= buffer_extent_offset) { | |
113 | // skip any image extent that is not included in the results | |
114 | break; | |
115 | } | |
116 | ||
117 | // current buffer-extent should be within the current image-extent | |
118 | ceph_assert(buffer_offset <= buffer_extent_offset && | |
119 | buffer_offset + image_length >= | |
120 | buffer_extent_offset + buffer_extent_length); | |
121 | auto image_extent_offset = | |
122 | image_offset + (buffer_extent_offset - buffer_offset); | |
123 | ldout(cct, 20) << "mapping buffer extent " << buffer_extent_offset | |
124 | << "~" << buffer_extent_length << " to image extent " | |
125 | << image_extent_offset << "~" << buffer_extent_length | |
126 | << dendl; | |
127 | sparse_bufferlist.extent_map->emplace_back( | |
128 | image_extent_offset, buffer_extent_length); | |
129 | ++bem_it; | |
130 | } | |
131 | ||
132 | buffer_offset += image_length; | |
133 | } | |
134 | ceph_assert(buffer_offset == buffer_extents_length); | |
135 | ceph_assert(bem_it == buffer_extent_map.end()); | |
136 | ||
137 | ldout(cct, 20) << "moved resulting " << *sparse_bufferlist.extent_map | |
9f95a23c TL |
138 | << " extents of total " << sparse_bufferlist.bl->length() |
139 | << " bytes to bl " | |
140 | << reinterpret_cast<void*>(sparse_bufferlist.bl) << dendl; | |
141 | } | |
7c673cae FG |
142 | }; |
143 | ||
11fdf7f2 | 144 | ReadResult::C_ImageReadRequest::C_ImageReadRequest( |
f67539c2 TL |
145 | AioCompletion *aio_completion, uint64_t buffer_offset, |
146 | const Extents image_extents) | |
147 | : aio_completion(aio_completion), buffer_offset(buffer_offset), | |
148 | image_extents(image_extents) { | |
7c673cae FG |
149 | aio_completion->add_request(); |
150 | } | |
151 | ||
7c673cae FG |
152 | void ReadResult::C_ImageReadRequest::finish(int r) { |
153 | CephContext *cct = aio_completion->ictx->cct; | |
154 | ldout(cct, 10) << "C_ImageReadRequest: r=" << r | |
155 | << dendl; | |
f67539c2 TL |
156 | if (r >= 0 || (ignore_enoent && r == -ENOENT)) { |
157 | striper::LightweightBufferExtents buffer_extents; | |
7c673cae FG |
158 | size_t length = 0; |
159 | for (auto &image_extent : image_extents) { | |
f67539c2 | 160 | buffer_extents.emplace_back(buffer_offset + length, image_extent.second); |
7c673cae FG |
161 | length += image_extent.second; |
162 | } | |
f67539c2 | 163 | ceph_assert(r == -ENOENT || length == bl.length()); |
7c673cae | 164 | |
9f95a23c | 165 | aio_completion->lock.lock(); |
7c673cae | 166 | aio_completion->read_result.m_destriper.add_partial_result( |
f67539c2 | 167 | cct, std::move(bl), buffer_extents); |
9f95a23c | 168 | aio_completion->lock.unlock(); |
7c673cae FG |
169 | r = length; |
170 | } | |
171 | ||
11fdf7f2 | 172 | aio_completion->complete_request(r); |
7c673cae FG |
173 | } |
174 | ||
11fdf7f2 | 175 | ReadResult::C_ObjectReadRequest::C_ObjectReadRequest( |
f67539c2 TL |
176 | AioCompletion *aio_completion, ReadExtents&& extents) |
177 | : aio_completion(aio_completion), extents(std::move(extents)) { | |
11fdf7f2 TL |
178 | aio_completion->add_request(); |
179 | } | |
180 | ||
181 | void ReadResult::C_ObjectReadRequest::finish(int r) { | |
7c673cae | 182 | CephContext *cct = aio_completion->ictx->cct; |
11fdf7f2 | 183 | ldout(cct, 10) << "C_ObjectReadRequest: r=" << r |
7c673cae FG |
184 | << dendl; |
185 | ||
11fdf7f2 | 186 | if (r == -ENOENT) { |
b32b8144 FG |
187 | r = 0; |
188 | } | |
189 | if (r >= 0) { | |
f67539c2 | 190 | uint64_t object_len = 0; |
9f95a23c | 191 | aio_completion->lock.lock(); |
f67539c2 TL |
192 | for (auto& extent: extents) { |
193 | ldout(cct, 10) << " got " << extent.extent_map | |
194 | << " for " << extent.buffer_extents | |
195 | << " bl " << extent.bl.length() << dendl; | |
196 | ||
9f95a23c | 197 | aio_completion->read_result.m_destriper.add_partial_sparse_result( |
f67539c2 TL |
198 | cct, std::move(extent.bl), extent.extent_map, extent.offset, |
199 | extent.buffer_extents); | |
200 | ||
201 | object_len += extent.length; | |
7c673cae | 202 | } |
9f95a23c | 203 | aio_completion->lock.unlock(); |
11fdf7f2 | 204 | r = object_len; |
7c673cae | 205 | } |
7c673cae | 206 | |
11fdf7f2 | 207 | aio_completion->complete_request(r); |
7c673cae FG |
208 | } |
209 | ||
f67539c2 TL |
210 | ReadResult::C_ObjectReadMergedExtents::C_ObjectReadMergedExtents( |
211 | CephContext* cct, ReadExtents* extents, Context* on_finish) | |
212 | : cct(cct), extents(extents), on_finish(on_finish) { | |
213 | } | |
214 | ||
215 | void ReadResult::C_ObjectReadMergedExtents::finish(int r) { | |
216 | if (r >= 0) { | |
217 | for (auto& extent: *extents) { | |
218 | if (bl.length() < extent.length) { | |
219 | lderr(cct) << "Merged extents length is less than expected" << dendl; | |
220 | r = -EIO; | |
221 | break; | |
222 | } | |
223 | bl.splice(0, extent.length, &extent.bl); | |
224 | } | |
225 | if (bl.length() != 0) { | |
226 | lderr(cct) << "Merged extents length is greater than expected" << dendl; | |
227 | r = -EIO; | |
228 | } | |
229 | } | |
230 | on_finish->complete(r); | |
231 | } | |
232 | ||
7c673cae FG |
233 | ReadResult::ReadResult() : m_buffer(Empty()) { |
234 | } | |
235 | ||
236 | ReadResult::ReadResult(char *buf, size_t buf_len) | |
237 | : m_buffer(Linear(buf, buf_len)) { | |
238 | } | |
239 | ||
240 | ReadResult::ReadResult(const struct iovec *iov, int iov_count) | |
241 | : m_buffer(Vector(iov, iov_count)) { | |
242 | } | |
243 | ||
244 | ReadResult::ReadResult(ceph::bufferlist *bl) | |
245 | : m_buffer(Bufferlist(bl)) { | |
246 | } | |
247 | ||
f67539c2 | 248 | ReadResult::ReadResult(Extents* extent_map, ceph::bufferlist* bl) |
9f95a23c TL |
249 | : m_buffer(SparseBufferlist(extent_map, bl)) { |
250 | } | |
251 | ||
f67539c2 TL |
252 | void ReadResult::set_image_extents(const Extents& image_extents) { |
253 | boost::apply_visitor(SetImageExtentsVisitor(image_extents), m_buffer); | |
7c673cae FG |
254 | } |
255 | ||
256 | void ReadResult::assemble_result(CephContext *cct) { | |
257 | boost::apply_visitor(AssembleResultVisitor(cct, m_destriper), m_buffer); | |
258 | } | |
259 | ||
260 | } // namespace io | |
261 | } // namespace librbd | |
262 |