]>
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" | |
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 | SetClipLengthVisitor(size_t length) : length(length) { | |
23 | } | |
24 | ||
25 | void operator()(Linear &linear) const { | |
26 | 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 = 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 | 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 | ||
82 | ReadResult::C_ReadRequest::C_ReadRequest(AioCompletion *aio_completion) | |
83 | : aio_completion(aio_completion) { | |
84 | aio_completion->add_request(); | |
85 | } | |
86 | ||
87 | void ReadResult::C_ReadRequest::finish(int r) { | |
88 | aio_completion->complete_request(r); | |
89 | } | |
90 | ||
91 | void ReadResult::C_ImageReadRequest::finish(int r) { | |
92 | CephContext *cct = aio_completion->ictx->cct; | |
93 | ldout(cct, 10) << "C_ImageReadRequest: r=" << r | |
94 | << dendl; | |
95 | if (r >= 0) { | |
96 | size_t length = 0; | |
97 | for (auto &image_extent : image_extents) { | |
98 | length += image_extent.second; | |
99 | } | |
100 | assert(length == bl.length()); | |
101 | ||
102 | aio_completion->lock.Lock(); | |
103 | aio_completion->read_result.m_destriper.add_partial_result( | |
104 | cct, bl, image_extents); | |
105 | aio_completion->lock.Unlock(); | |
106 | r = length; | |
107 | } | |
108 | ||
109 | C_ReadRequest::finish(r); | |
110 | } | |
111 | ||
112 | void ReadResult::C_SparseReadRequestBase::finish(ExtentMap &extent_map, | |
113 | const Extents &buffer_extents, | |
114 | uint64_t offset, size_t length, | |
115 | bufferlist &bl, int r) { | |
7c673cae FG |
116 | CephContext *cct = aio_completion->ictx->cct; |
117 | ldout(cct, 10) << "C_SparseReadRequestBase: r = " << r | |
118 | << dendl; | |
119 | ||
b32b8144 FG |
120 | if (ignore_enoent && r == -ENOENT) { |
121 | r = 0; | |
122 | } | |
123 | if (r >= 0) { | |
7c673cae FG |
124 | ldout(cct, 10) << " got " << extent_map |
125 | << " for " << buffer_extents | |
126 | << " bl " << bl.length() << dendl; | |
b32b8144 | 127 | // handle the case where a sparse-read wasn't issued |
7c673cae FG |
128 | if (extent_map.empty()) { |
129 | extent_map[offset] = bl.length(); | |
130 | } | |
131 | ||
b32b8144 | 132 | aio_completion->lock.Lock(); |
7c673cae FG |
133 | aio_completion->read_result.m_destriper.add_partial_sparse_result( |
134 | cct, bl, extent_map, offset, buffer_extents); | |
b32b8144 FG |
135 | aio_completion->lock.Unlock(); |
136 | ||
7c673cae FG |
137 | r = length; |
138 | } | |
7c673cae FG |
139 | |
140 | C_ReadRequest::finish(r); | |
141 | } | |
142 | ||
143 | ReadResult::ReadResult() : m_buffer(Empty()) { | |
144 | } | |
145 | ||
146 | ReadResult::ReadResult(char *buf, size_t buf_len) | |
147 | : m_buffer(Linear(buf, buf_len)) { | |
148 | } | |
149 | ||
150 | ReadResult::ReadResult(const struct iovec *iov, int iov_count) | |
151 | : m_buffer(Vector(iov, iov_count)) { | |
152 | } | |
153 | ||
154 | ReadResult::ReadResult(ceph::bufferlist *bl) | |
155 | : m_buffer(Bufferlist(bl)) { | |
156 | } | |
157 | ||
158 | void ReadResult::set_clip_length(size_t length) { | |
159 | boost::apply_visitor(SetClipLengthVisitor(length), m_buffer); | |
160 | } | |
161 | ||
162 | void ReadResult::assemble_result(CephContext *cct) { | |
163 | boost::apply_visitor(AssembleResultVisitor(cct, m_destriper), m_buffer); | |
164 | } | |
165 | ||
166 | } // namespace io | |
167 | } // namespace librbd | |
168 |