]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/io/ReadResult.cc
Import ceph 15.2.8
[ceph.git] / ceph / src / librbd / io / ReadResult.cc
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"
8 #include <boost/variant/apply_visitor.hpp>
9 #include <boost/variant/static_visitor.hpp>
10
11 #define dout_subsys ceph_subsys_rbd
12 #undef dout_prefix
13 #define dout_prefix *_dout << "librbd::io::ReadResult: " << this \
14 << " " << __func__ << ": "
15
16 namespace librbd {
17 namespace io {
18
19 struct ReadResult::SetClipLengthVisitor : public boost::static_visitor<void> {
20 size_t length;
21
22 explicit SetClipLengthVisitor(size_t length) : length(length) {
23 }
24
25 void operator()(Linear &linear) const {
26 ceph_assert(length <= linear.buf_len);
27 linear.buf_len = length;
28 }
29
30 template <typename T>
31 void operator()(T &t) const {
32 }
33 };
34
35 struct ReadResult::AssembleResultVisitor : public boost::static_visitor<void> {
36 CephContext *cct;
37 Striper::StripedReadResult &destriper;
38
39 AssembleResultVisitor(CephContext *cct, Striper::StripedReadResult &destriper)
40 : cct(cct), destriper(destriper) {
41 }
42
43 void operator()(Empty &empty) const {
44 ldout(cct, 20) << "dropping read result" << dendl;
45 }
46
47 void operator()(Linear &linear) const {
48 ldout(cct, 20) << "copying resulting bytes to "
49 << reinterpret_cast<void*>(linear.buf) << dendl;
50 destriper.assemble_result(cct, linear.buf, linear.buf_len);
51 }
52
53 void operator()(Vector &vector) const {
54 bufferlist bl;
55 destriper.assemble_result(cct, bl, true);
56
57 ldout(cct, 20) << "copying resulting " << bl.length() << " bytes to iovec "
58 << reinterpret_cast<const void*>(vector.iov) << dendl;
59
60 bufferlist::iterator it = bl.begin();
61 size_t length = bl.length();
62 size_t offset = 0;
63 int idx = 0;
64 for (; offset < length && idx < vector.iov_count; idx++) {
65 size_t len = std::min(vector.iov[idx].iov_len, length - offset);
66 it.copy(len, static_cast<char *>(vector.iov[idx].iov_base));
67 offset += len;
68 }
69 ceph_assert(offset == bl.length());
70 }
71
72 void operator()(Bufferlist &bufferlist) const {
73 bufferlist.bl->clear();
74 destriper.assemble_result(cct, *bufferlist.bl, true);
75
76 ldout(cct, 20) << "moved resulting " << bufferlist.bl->length() << " "
77 << "bytes to bl " << reinterpret_cast<void*>(bufferlist.bl)
78 << dendl;
79 }
80
81 void operator()(SparseBufferlist &sparse_bufferlist) const {
82 sparse_bufferlist.extent_map->clear();
83 sparse_bufferlist.bl->clear();
84 destriper.assemble_result(cct, sparse_bufferlist.extent_map,
85 sparse_bufferlist.bl);
86
87 ldout(cct, 20) << "moved resulting " << sparse_bufferlist.extent_map->size()
88 << " extents of total " << sparse_bufferlist.bl->length()
89 << " bytes to bl "
90 << reinterpret_cast<void*>(sparse_bufferlist.bl) << dendl;
91 }
92 };
93
94 ReadResult::C_ImageReadRequest::C_ImageReadRequest(
95 AioCompletion *aio_completion, const Extents image_extents)
96 : aio_completion(aio_completion), image_extents(image_extents) {
97 aio_completion->add_request();
98 }
99
100 void ReadResult::C_ImageReadRequest::finish(int r) {
101 CephContext *cct = aio_completion->ictx->cct;
102 ldout(cct, 10) << "C_ImageReadRequest: r=" << r
103 << dendl;
104 if (r >= 0) {
105 size_t length = 0;
106 for (auto &image_extent : image_extents) {
107 length += image_extent.second;
108 }
109 ceph_assert(length == bl.length());
110
111 aio_completion->lock.lock();
112 aio_completion->read_result.m_destriper.add_partial_result(
113 cct, bl, image_extents);
114 aio_completion->lock.unlock();
115 r = length;
116 }
117
118 aio_completion->complete_request(r);
119 }
120
121 ReadResult::C_ObjectReadRequest::C_ObjectReadRequest(
122 AioCompletion *aio_completion, uint64_t object_off, uint64_t object_len,
123 LightweightBufferExtents&& buffer_extents)
124 : aio_completion(aio_completion), object_off(object_off),
125 object_len(object_len), buffer_extents(std::move(buffer_extents)) {
126 aio_completion->add_request();
127 }
128
129 void ReadResult::C_ObjectReadRequest::finish(int r) {
130 CephContext *cct = aio_completion->ictx->cct;
131 ldout(cct, 10) << "C_ObjectReadRequest: r=" << r
132 << dendl;
133
134 if (r == -ENOENT) {
135 r = 0;
136 }
137 if (r >= 0) {
138 ldout(cct, 10) << " got " << extent_map
139 << " for " << buffer_extents
140 << " bl " << bl.length() << dendl;
141 aio_completion->lock.lock();
142 if (!extent_map.empty()) {
143 aio_completion->read_result.m_destriper.add_partial_sparse_result(
144 cct, bl, extent_map, object_off, buffer_extents);
145 } else {
146 // handle the case where a sparse-read wasn't issued
147 aio_completion->read_result.m_destriper.add_partial_result(
148 cct, std::move(bl), buffer_extents);
149 }
150 aio_completion->lock.unlock();
151
152 r = object_len;
153 }
154
155 aio_completion->complete_request(r);
156 }
157
158 ReadResult::ReadResult() : m_buffer(Empty()) {
159 }
160
161 ReadResult::ReadResult(char *buf, size_t buf_len)
162 : m_buffer(Linear(buf, buf_len)) {
163 }
164
165 ReadResult::ReadResult(const struct iovec *iov, int iov_count)
166 : m_buffer(Vector(iov, iov_count)) {
167 }
168
169 ReadResult::ReadResult(ceph::bufferlist *bl)
170 : m_buffer(Bufferlist(bl)) {
171 }
172
173 ReadResult::ReadResult(std::map<uint64_t, uint64_t> *extent_map,
174 ceph::bufferlist *bl)
175 : m_buffer(SparseBufferlist(extent_map, bl)) {
176 }
177
178 void ReadResult::set_clip_length(size_t length) {
179 boost::apply_visitor(SetClipLengthVisitor(length), m_buffer);
180 }
181
182 void ReadResult::assemble_result(CephContext *cct) {
183 boost::apply_visitor(AssembleResultVisitor(cct, m_destriper), m_buffer);
184 }
185
186 } // namespace io
187 } // namespace librbd
188