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