Skip to content

Commit 4527b8c

Browse files
jamieprydeaainscow
authored andcommitted
erasure-code: Add parity delta write optimization to Jerasure
This commit adds FLAG_EC_PLUGIN_PARITY_DELTA_OPTIMIZATION to the list of optimizations supported by the Jerasure plugin, and encode_delta and apply_delta functions for all Jerasure techniques. Signed-off-by: Jamie Pryde <[email protected]> Signed-off-by: Alex Ainscow <[email protected]>
1 parent fc73f66 commit 4527b8c

File tree

3 files changed

+158
-3
lines changed

3 files changed

+158
-3
lines changed

src/erasure-code/jerasure/ErasureCodeJerasure.cc

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,18 @@ int ErasureCodeJerasure::decode_chunks(const set<int> &want_to_read,
137137
return jerasure_decode(erasures, data, coding, blocksize);
138138
}
139139

140+
void ErasureCodeJerasure::encode_delta(const bufferptr &old_data,
141+
const bufferptr &new_data,
142+
bufferptr *delta_maybe_in_place)
143+
{
144+
if (&old_data != delta_maybe_in_place) {
145+
memcpy(delta_maybe_in_place->c_str(), old_data.c_str(), delta_maybe_in_place->length());
146+
}
147+
char *new_data_p = const_cast<char*>(new_data.c_str());
148+
char *delta_p = delta_maybe_in_place->c_str();
149+
galois_region_xor(new_data_p, delta_p, delta_maybe_in_place->length());
150+
}
151+
140152
bool ErasureCodeJerasure::is_prime(int value)
141153
{
142154
int prime55[] = {
@@ -152,7 +164,86 @@ bool ErasureCodeJerasure::is_prime(int value)
152164
return false;
153165
}
154166

155-
//
167+
void ErasureCodeJerasure::matrix_apply_delta(const shard_id_map<bufferptr> &in,
168+
shard_id_map<bufferptr> &out,
169+
int k, int w, int *matrix)
170+
{
171+
auto first = in.begin();
172+
const unsigned blocksize = first->second.length();
173+
174+
for (auto const& [datashard, databuf] : in) {
175+
if (datashard < k) {
176+
for (auto const& [codingshard, codingbuf] : out) {
177+
if (codingshard >= k) {
178+
ceph_assert(codingbuf.length() == blocksize);
179+
char* input_data = const_cast<char*>(databuf.c_str());
180+
char* output_data = const_cast<char*>(codingbuf.c_str());
181+
if (static_cast<int>(codingshard) == k) {
182+
galois_region_xor(input_data, output_data, blocksize);
183+
}
184+
else {
185+
switch (w) {
186+
case 8:
187+
galois_w08_region_multiply(input_data, matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))], blocksize, output_data, 1);
188+
break;
189+
case 16:
190+
galois_w16_region_multiply(input_data, matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))], blocksize, output_data, 1);
191+
break;
192+
case 32:
193+
galois_w32_region_multiply(input_data, matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))], blocksize, output_data, 1);
194+
break;
195+
}
196+
}
197+
}
198+
}
199+
}
200+
}
201+
}
202+
203+
void ErasureCodeJerasure::do_scheduled_ops(char **ptrs, int **operations, int packetsize, int s, int d)
204+
{
205+
char *sptr;
206+
char *dptr;
207+
int op;
208+
209+
for (op = 0; operations[op][0] >= 0; op++) {
210+
if (operations[op][0] == s && operations[op][2] == d) {
211+
sptr = ptrs[0] + operations[op][1]*packetsize;
212+
dptr = ptrs[1] + operations[op][3]*packetsize;
213+
galois_region_xor(sptr, dptr, packetsize);
214+
}
215+
}
216+
}
217+
218+
void ErasureCodeJerasure::schedule_apply_delta(const shard_id_map<bufferptr> &in,
219+
shard_id_map<bufferptr> &out,
220+
int k, int w, int packetsize,
221+
int ** simple_schedule)
222+
{
223+
auto first = in.begin();
224+
unsigned int blocksize = first->second.length();
225+
226+
for (auto const& [datashard, databuf] : in) {
227+
if (datashard < k) {
228+
for (auto const& [codingshard, codingbuf] : out) {
229+
if (codingshard >= k) {
230+
ceph_assert(codingbuf.length() == blocksize);
231+
char * ptr_copy[2];
232+
ptr_copy[0] = const_cast<char*>(databuf.c_str());
233+
ptr_copy[1] = const_cast<char*>(codingbuf.c_str());
234+
unsigned int done;
235+
for (done = 0; done < blocksize; done += (packetsize*w)) {
236+
do_scheduled_ops(ptr_copy, simple_schedule, packetsize, static_cast<int>(datashard), static_cast<int>(codingshard));
237+
ptr_copy[0] += (packetsize*w);
238+
ptr_copy[1] += (packetsize*w);
239+
}
240+
}
241+
}
242+
}
243+
}
244+
}
245+
246+
//
156247
// ErasureCodeJerasureReedSolomonVandermonde
157248
//
158249
void ErasureCodeJerasureReedSolomonVandermonde::jerasure_encode(char **data,
@@ -171,6 +262,12 @@ int ErasureCodeJerasureReedSolomonVandermonde::jerasure_decode(int *erasures,
171262
erasures, data, coding, blocksize);
172263
}
173264

265+
void ErasureCodeJerasureReedSolomonVandermonde::apply_delta(const shard_id_map<bufferptr> &in,
266+
shard_id_map<bufferptr> &out)
267+
{
268+
matrix_apply_delta(in, out, k, w, matrix);
269+
}
270+
174271
unsigned ErasureCodeJerasureReedSolomonVandermonde::get_alignment() const
175272
{
176273
if (per_chunk_alignment) {
@@ -221,6 +318,12 @@ int ErasureCodeJerasureReedSolomonRAID6::jerasure_decode(int *erasures,
221318
return jerasure_matrix_decode(k, m, w, matrix, 1, erasures, data, coding, blocksize);
222319
}
223320

321+
void ErasureCodeJerasureReedSolomonRAID6::apply_delta(const shard_id_map<bufferptr> &in,
322+
shard_id_map<bufferptr> &out)
323+
{
324+
matrix_apply_delta(in, out, k, w, matrix);
325+
}
326+
224327
unsigned ErasureCodeJerasureReedSolomonRAID6::get_alignment() const
225328
{
226329
if (per_chunk_alignment) {
@@ -275,6 +378,12 @@ int ErasureCodeJerasureCauchy::jerasure_decode(int *erasures,
275378
erasures, data, coding, blocksize, packetsize, 1);
276379
}
277380

381+
void ErasureCodeJerasureCauchy::apply_delta(const shard_id_map<bufferptr> &in,
382+
shard_id_map<bufferptr> &out)
383+
{
384+
schedule_apply_delta(in, out, k, w, packetsize, simple_schedule);
385+
}
386+
278387
unsigned ErasureCodeJerasureCauchy::get_alignment() const
279388
{
280389
if (per_chunk_alignment) {
@@ -305,6 +414,7 @@ void ErasureCodeJerasureCauchy::prepare_schedule(int *matrix)
305414
{
306415
bitmatrix = jerasure_matrix_to_bitmatrix(k, m, w, matrix);
307416
schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix);
417+
simple_schedule = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix);
308418
}
309419

310420
ErasureCodeJerasureCauchy::~ErasureCodeJerasureCauchy()
@@ -313,6 +423,8 @@ ErasureCodeJerasureCauchy::~ErasureCodeJerasureCauchy()
313423
free(bitmatrix);
314424
if (schedule)
315425
jerasure_free_schedule(schedule);
426+
if (simple_schedule)
427+
jerasure_free_schedule(simple_schedule);
316428
}
317429

318430
//
@@ -344,6 +456,8 @@ ErasureCodeJerasureLiberation::~ErasureCodeJerasureLiberation()
344456
free(bitmatrix);
345457
if (schedule)
346458
jerasure_free_schedule(schedule);
459+
if (simple_schedule)
460+
jerasure_free_schedule(simple_schedule);
347461
}
348462

349463
void ErasureCodeJerasureLiberation::jerasure_encode(char **data,
@@ -363,6 +477,12 @@ int ErasureCodeJerasureLiberation::jerasure_decode(int *erasures,
363477
coding, blocksize, packetsize, 1);
364478
}
365479

480+
void ErasureCodeJerasureLiberation::apply_delta(const shard_id_map<bufferptr> &in,
481+
shard_id_map<bufferptr> &out)
482+
{
483+
schedule_apply_delta(in, out, k, w, packetsize, simple_schedule);
484+
}
485+
366486
unsigned ErasureCodeJerasureLiberation::get_alignment() const
367487
{
368488
unsigned alignment = k*w*packetsize*sizeof(int);
@@ -451,6 +571,7 @@ void ErasureCodeJerasureLiberation::prepare()
451571
{
452572
bitmatrix = liberation_coding_bitmatrix(k, w);
453573
schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix);
574+
simple_schedule = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix);
454575
}
455576

456577
//
@@ -475,6 +596,7 @@ void ErasureCodeJerasureBlaumRoth::prepare()
475596
{
476597
bitmatrix = blaum_roth_coding_bitmatrix(k, w);
477598
schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix);
599+
simple_schedule = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix);
478600
}
479601

480602
//
@@ -512,4 +634,5 @@ void ErasureCodeJerasureLiber8tion::prepare()
512634
{
513635
bitmatrix = liber8tion_coding_bitmatrix(k);
514636
schedule = jerasure_smart_bitmatrix_to_schedule(k, m, w, bitmatrix);
637+
simple_schedule = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix);
515638
}

src/erasure-code/jerasure/ErasureCodeJerasure.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ class ErasureCodeJerasure : public ceph::ErasureCode {
4949
uint64_t get_supported_optimizations() const override {
5050
return FLAG_EC_PLUGIN_PARTIAL_READ_OPTIMIZATION |
5151
FLAG_EC_PLUGIN_PARTIAL_WRITE_OPTIMIZATION |
52-
FLAG_EC_PLUGIN_ZERO_INPUT_ZERO_OUTPUT_OPTIMIZATION;
52+
FLAG_EC_PLUGIN_ZERO_INPUT_ZERO_OUTPUT_OPTIMIZATION |
53+
FLAG_EC_PLUGIN_PARITY_DELTA_OPTIMIZATION;
5354
}
5455

5556

@@ -70,6 +71,13 @@ class ErasureCodeJerasure : public ceph::ErasureCode {
7071
const std::map<int, ceph::buffer::list> &chunks,
7172
std::map<int, ceph::buffer::list> *decoded) override;
7273

74+
void encode_delta(const ceph::bufferptr &old_data,
75+
const ceph::bufferptr &new_data,
76+
ceph::bufferptr *delta_maybe_in_place);
77+
78+
void apply_delta(const shard_id_map<ceph::bufferptr> &in,
79+
shard_id_map<ceph::bufferptr> &out) = 0;
80+
7381
int init(ceph::ErasureCodeProfile &profile, std::ostream *ss) override;
7482

7583
virtual void jerasure_encode(char **data,
@@ -82,6 +90,18 @@ class ErasureCodeJerasure : public ceph::ErasureCode {
8290
virtual unsigned get_alignment() const = 0;
8391
virtual void prepare() = 0;
8492
static bool is_prime(int value);
93+
94+
void matrix_apply_delta(const shard_id_map<bufferptr> &in,
95+
shard_id_map<bufferptr> &out,
96+
int k, int w, int *matrix);
97+
98+
void schedule_apply_delta(const shard_id_map<bufferptr> &in,
99+
shard_id_map<bufferptr> &out,
100+
int k, int w, int packetsize,
101+
int ** simple_schedule);
102+
103+
void do_scheduled_ops(char **ptrs, int **operations, int packetsize, int s, int d);
104+
85105
protected:
86106
virtual int parse(ceph::ErasureCodeProfile &profile, std::ostream *ss);
87107
};
@@ -109,6 +129,8 @@ class ErasureCodeJerasureReedSolomonVandermonde : public ErasureCodeJerasure {
109129
char **data,
110130
char **coding,
111131
int blocksize) override;
132+
void apply_delta(const shard_id_map<ceph::bufferptr> &in,
133+
shard_id_map<ceph::bufferptr> &out) override;
112134
unsigned get_alignment() const override;
113135
size_t get_minimum_granularity() override
114136
{
@@ -143,6 +165,8 @@ class ErasureCodeJerasureReedSolomonRAID6 : public ErasureCodeJerasure {
143165
char **data,
144166
char **coding,
145167
int blocksize) override;
168+
void apply_delta(const shard_id_map<ceph::bufferptr> &in,
169+
shard_id_map<ceph::bufferptr> &out) override;
146170
unsigned get_alignment() const override;
147171
size_t get_minimum_granularity() override
148172
{
@@ -159,12 +183,14 @@ class ErasureCodeJerasureCauchy : public ErasureCodeJerasure {
159183
public:
160184
int *bitmatrix;
161185
int **schedule;
186+
int **simple_schedule;
162187
int packetsize;
163188

164189
explicit ErasureCodeJerasureCauchy(const char *technique) :
165190
ErasureCodeJerasure(technique),
166191
bitmatrix(0),
167192
schedule(0),
193+
simple_schedule(0),
168194
packetsize(0)
169195
{
170196
DEFAULT_K = "7";
@@ -180,6 +206,8 @@ class ErasureCodeJerasureCauchy : public ErasureCodeJerasure {
180206
char **data,
181207
char **coding,
182208
int blocksize) override;
209+
void apply_delta(const shard_id_map<ceph::bufferptr> &in,
210+
shard_id_map<ceph::bufferptr> &out) override;
183211
unsigned get_alignment() const override;
184212
size_t get_minimum_granularity() override
185213
{
@@ -212,12 +240,14 @@ class ErasureCodeJerasureLiberation : public ErasureCodeJerasure {
212240
public:
213241
int *bitmatrix;
214242
int **schedule;
243+
int **simple_schedule;
215244
int packetsize;
216245

217246
explicit ErasureCodeJerasureLiberation(const char *technique = "liberation") :
218247
ErasureCodeJerasure(technique),
219248
bitmatrix(0),
220249
schedule(0),
250+
simple_schedule(0),
221251
packetsize(0)
222252
{
223253
DEFAULT_K = "2";
@@ -233,6 +263,8 @@ class ErasureCodeJerasureLiberation : public ErasureCodeJerasure {
233263
char **data,
234264
char **coding,
235265
int blocksize) override;
266+
void apply_delta(const shard_id_map<ceph::bufferptr> &in,
267+
shard_id_map<ceph::bufferptr> &out) override;
236268
unsigned get_alignment() const override;
237269
size_t get_minimum_granularity() override
238270
{

src/test/erasure-code/TestErasureCodePlugins.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ INSTANTIATE_TEST_SUITE_P(
613613
"plugin=lrc mapping=_D_D_DDD layers=[[\"cDcDcDDD\",\"\"]]",
614614
"plugin=lrc mapping=_D_D_DDDD layers=[[\"cDcDcDDDD\",\"\"]]",
615615
"plugin=jerasure technique=reed_sol_van k=6 m=3 w=16",
616-
"plugin=jerasure technique=reed_sol_van k=6 m=3 w=32"
616+
"plugin=jerasure technique=reed_sol_van k=6 m=3 w=32",
617617
"plugin=jerasure technique=liberation k=6 m=2 packetsize=32 w=11",
618618
"plugin=jerasure technique=liberation k=6 m=2 packetsize=36 w=13",
619619
"plugin=jerasure technique=blaum_roth k=6 m=2 packetsize=44 w=7",

0 commit comments

Comments
 (0)