Skip to content

Commit d9eda19

Browse files
committed
osd: Re-introduce ECUtil
Signed-off-by: Alex Ainscow <[email protected]>
1 parent 182473f commit d9eda19

File tree

4 files changed

+540
-0
lines changed

4 files changed

+540
-0
lines changed

src/crimson/osd/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ add_executable(crimson-osd
4545
objclass.cc
4646
${PROJECT_SOURCE_DIR}/src/objclass/class_api.cc
4747
${PROJECT_SOURCE_DIR}/src/osd/ClassHandler.cc
48+
${PROJECT_SOURCE_DIR}/src/osd/ECUtil.cc
4849
${PROJECT_SOURCE_DIR}/src/osd/ECUtilL.cc
4950
${PROJECT_SOURCE_DIR}/src/osd/osd_op_util.cc
5051
${PROJECT_SOURCE_DIR}/src/osd/OSDCap.cc

src/osd/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ set(osd_srcs
4646
ECExtentCacheL.cc
4747
ECTransactionL.cc
4848
ECUtilL.cc
49+
ECUtil.cc
4950
${CMAKE_SOURCE_DIR}/src/common/TrackedOp.cc
5051
${CMAKE_SOURCE_DIR}/src/mgr/OSDPerfMetricTypes.cc
5152
${osd_cyg_functions_src}

src/osd/ECUtil.cc

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2+
3+
#include <errno.h>
4+
#include "common/ceph_context.h"
5+
#include "global/global_context.h"
6+
#include "include/encoding.h"
7+
#include "ECUtil.h"
8+
9+
using namespace std;
10+
using ceph::bufferlist;
11+
using ceph::ErasureCodeInterfaceRef;
12+
using ceph::Formatter;
13+
14+
std::pair<uint64_t, uint64_t> ECUtil::stripe_info_t::chunk_aligned_offset_len_to_chunk(
15+
std::pair<uint64_t, uint64_t> in) const {
16+
pair<uint64_t, uint64_t> tmp = offset_len_to_stripe_bounds(in);
17+
return std::make_pair(
18+
chunk_aligned_logical_offset_to_chunk_offset(tmp.first),
19+
chunk_aligned_logical_size_to_chunk_size(tmp.second));
20+
}
21+
22+
int ECUtil::decode(
23+
const stripe_info_t &sinfo,
24+
ErasureCodeInterfaceRef &ec_impl,
25+
const set<int> want_to_read,
26+
map<int, bufferlist> &to_decode,
27+
bufferlist *out)
28+
{
29+
ceph_assert(to_decode.size());
30+
31+
uint64_t total_data_size = to_decode.begin()->second.length();
32+
ceph_assert(total_data_size % sinfo.get_chunk_size() == 0);
33+
34+
ceph_assert(out);
35+
ceph_assert(out->length() == 0);
36+
37+
for (map<int, bufferlist>::iterator i = to_decode.begin();
38+
i != to_decode.end();
39+
++i) {
40+
ceph_assert(i->second.length() == total_data_size);
41+
}
42+
43+
if (total_data_size == 0)
44+
return 0;
45+
46+
for (uint64_t i = 0; i < total_data_size; i += sinfo.get_chunk_size()) {
47+
map<int, bufferlist> chunks;
48+
for (map<int, bufferlist>::iterator j = to_decode.begin();
49+
j != to_decode.end();
50+
++j) {
51+
chunks[j->first].substr_of(j->second, i, sinfo.get_chunk_size());
52+
}
53+
bufferlist bl;
54+
int r = ec_impl->decode_concat(want_to_read, chunks, &bl);
55+
ceph_assert(r == 0);
56+
ceph_assert(bl.length() % sinfo.get_chunk_size() == 0);
57+
out->claim_append(bl);
58+
}
59+
return 0;
60+
}
61+
62+
int ECUtil::decode(
63+
const stripe_info_t &sinfo,
64+
ErasureCodeInterfaceRef &ec_impl,
65+
map<int, bufferlist> &to_decode,
66+
map<int, bufferlist*> &out) {
67+
68+
ceph_assert(to_decode.size());
69+
70+
for (auto &&i : to_decode) {
71+
if(i.second.length() == 0)
72+
return 0;
73+
}
74+
75+
set<int> need;
76+
for (map<int, bufferlist*>::iterator i = out.begin();
77+
i != out.end();
78+
++i) {
79+
ceph_assert(i->second);
80+
ceph_assert(i->second->length() == 0);
81+
need.insert(i->first);
82+
}
83+
84+
set<int> avail;
85+
for (auto &&i : to_decode) {
86+
ceph_assert(i.second.length() != 0);
87+
avail.insert(i.first);
88+
}
89+
90+
map<int, vector<pair<int, int>>> min;
91+
int r = ec_impl->minimum_to_decode(need, avail, &min);
92+
ceph_assert(r == 0);
93+
94+
int chunks_count = 0;
95+
int repair_data_per_chunk = 0;
96+
int subchunk_size = sinfo.get_chunk_size()/ec_impl->get_sub_chunk_count();
97+
98+
for (auto &&i : to_decode) {
99+
auto found = min.find(i.first);
100+
if (found != min.end()) {
101+
int repair_subchunk_count = 0;
102+
for (auto& subchunks : min[i.first]) {
103+
repair_subchunk_count += subchunks.second;
104+
}
105+
repair_data_per_chunk = repair_subchunk_count * subchunk_size;
106+
chunks_count = (int)i.second.length() / repair_data_per_chunk;
107+
break;
108+
}
109+
}
110+
111+
for (int i = 0; i < chunks_count; i++) {
112+
map<int, bufferlist> chunks;
113+
for (auto j = to_decode.begin();
114+
j != to_decode.end();
115+
++j) {
116+
chunks[j->first].substr_of(j->second,
117+
i*repair_data_per_chunk,
118+
repair_data_per_chunk);
119+
}
120+
map<int, bufferlist> out_bls;
121+
r = ec_impl->decode(need, chunks, &out_bls, sinfo.get_chunk_size());
122+
ceph_assert(r == 0);
123+
for (auto j = out.begin(); j != out.end(); ++j) {
124+
ceph_assert(out_bls.count(j->first));
125+
ceph_assert(out_bls[j->first].length() == sinfo.get_chunk_size());
126+
j->second->claim_append(out_bls[j->first]);
127+
}
128+
}
129+
for (auto &&i : out) {
130+
ceph_assert(i.second->length() == chunks_count * sinfo.get_chunk_size());
131+
}
132+
return 0;
133+
}
134+
135+
int ECUtil::encode(
136+
const stripe_info_t &sinfo,
137+
ErasureCodeInterfaceRef &ec_impl,
138+
bufferlist &in,
139+
const set<int> &want,
140+
map<int, bufferlist> *out) {
141+
142+
uint64_t logical_size = in.length();
143+
144+
ceph_assert(logical_size % sinfo.get_stripe_width() == 0);
145+
ceph_assert(out);
146+
ceph_assert(out->empty());
147+
148+
if (logical_size == 0)
149+
return 0;
150+
151+
for (uint64_t i = 0; i < logical_size; i += sinfo.get_stripe_width()) {
152+
map<int, bufferlist> encoded;
153+
bufferlist buf;
154+
buf.substr_of(in, i, sinfo.get_stripe_width());
155+
int r = ec_impl->encode(want, buf, &encoded);
156+
ceph_assert(r == 0);
157+
for (map<int, bufferlist>::iterator i = encoded.begin();
158+
i != encoded.end();
159+
++i) {
160+
ceph_assert(i->second.length() == sinfo.get_chunk_size());
161+
(*out)[i->first].claim_append(i->second);
162+
}
163+
}
164+
165+
for (map<int, bufferlist>::iterator i = out->begin();
166+
i != out->end();
167+
++i) {
168+
ceph_assert(i->second.length() % sinfo.get_chunk_size() == 0);
169+
ceph_assert(
170+
sinfo.aligned_chunk_offset_to_logical_offset(i->second.length()) ==
171+
logical_size);
172+
}
173+
return 0;
174+
}
175+
176+
void ECUtil::HashInfo::append(uint64_t old_size,
177+
map<int, bufferlist> &to_append) {
178+
ceph_assert(old_size == total_chunk_size);
179+
uint64_t size_to_append = to_append.begin()->second.length();
180+
if (has_chunk_hash()) {
181+
ceph_assert(to_append.size() == cumulative_shard_hashes.size());
182+
for (map<int, bufferlist>::iterator i = to_append.begin();
183+
i != to_append.end();
184+
++i) {
185+
ceph_assert(size_to_append == i->second.length());
186+
ceph_assert((unsigned)i->first < cumulative_shard_hashes.size());
187+
uint32_t new_hash = i->second.crc32c(cumulative_shard_hashes[i->first]);
188+
cumulative_shard_hashes[i->first] = new_hash;
189+
}
190+
}
191+
total_chunk_size += size_to_append;
192+
}
193+
194+
void ECUtil::HashInfo::encode(bufferlist &bl) const
195+
{
196+
ENCODE_START(1, 1, bl);
197+
encode(total_chunk_size, bl);
198+
encode(cumulative_shard_hashes, bl);
199+
ENCODE_FINISH(bl);
200+
}
201+
202+
void ECUtil::HashInfo::decode(bufferlist::const_iterator &bl)
203+
{
204+
DECODE_START(1, bl);
205+
decode(total_chunk_size, bl);
206+
decode(cumulative_shard_hashes, bl);
207+
projected_total_chunk_size = total_chunk_size;
208+
DECODE_FINISH(bl);
209+
}
210+
211+
void ECUtil::HashInfo::dump(Formatter *f) const
212+
{
213+
f->dump_unsigned("total_chunk_size", total_chunk_size);
214+
f->open_array_section("cumulative_shard_hashes");
215+
for (unsigned i = 0; i != cumulative_shard_hashes.size(); ++i) {
216+
f->open_object_section("hash");
217+
f->dump_unsigned("shard", i);
218+
f->dump_unsigned("hash", cumulative_shard_hashes[i]);
219+
f->close_section();
220+
}
221+
f->close_section();
222+
}
223+
224+
namespace ECUtil {
225+
std::ostream& operator<<(std::ostream& out, const HashInfo& hi)
226+
{
227+
ostringstream hashes;
228+
for (auto hash: hi.cumulative_shard_hashes)
229+
hashes << " " << hex << hash;
230+
return out << "tcs=" << hi.total_chunk_size << hashes.str();
231+
}
232+
}
233+
234+
void ECUtil::HashInfo::generate_test_instances(list<HashInfo*>& o)
235+
{
236+
o.push_back(new HashInfo(3));
237+
{
238+
bufferlist bl;
239+
bl.append_zero(20);
240+
map<int, bufferlist> buffers;
241+
buffers[0] = bl;
242+
buffers[1] = bl;
243+
buffers[2] = bl;
244+
o.back()->append(0, buffers);
245+
o.back()->append(20, buffers);
246+
}
247+
o.push_back(new HashInfo(4));
248+
}
249+
250+
const string HINFO_KEY = "hinfo_key";
251+
252+
bool ECUtil::is_hinfo_key_string(const string &key)
253+
{
254+
return key == HINFO_KEY;
255+
}
256+
257+
const string &ECUtil::get_hinfo_key()
258+
{
259+
return HINFO_KEY;
260+
}

0 commit comments

Comments
 (0)