*ss << "m=" << m << " must be >= 1" << std::endl;
return -EINVAL;
}
- int max_k_plus_m = std::numeric_limits<decltype(shard_id_t::id)>::max();
+ auto max_k_plus_m = std::numeric_limits<decltype(shard_id_t::id)>::max();
if (k+m > max_k_plus_m) {
*ss << "(k+m)=" << (k+m) << " must be <= " << max_k_plus_m << std::endl;
return -EINVAL;
set<int> *minimum)
{
if (includes(available_chunks.begin(), available_chunks.end(),
- want_to_read.begin(), want_to_read.end())) {
+ want_to_read.begin(), want_to_read.end())) {
*minimum = want_to_read;
} else {
unsigned int k = get_data_chunk_count();
(*decoded)[i].rebuild_aligned(SIMD_ALIGN);
}
bufferlist &bl = (*decoded)[i];
- if (bl.length() != bl.begin().get_current_ptr().length()) {
+ if (!bl.is_contiguous()) {
bl.rebuild();
}
}
virtual int minimum_to_decode(const shard_id_set &want_to_read,
const shard_id_set &available,
shard_id_set &minimum_set,
- mini_flat_map<shard_id_t, std::vector<std::pair<int, int>>>
- *minimum_sub_chunks) = 0;
+ mini_flat_map<shard_id_t, std::vector<std::pair<int, int>>> *minimum_sub_chunks) = 0;
// Interface for legacy EC.
[[deprecated]]
virtual int minimum_to_decode(const std::set<int> &want_to_read,
const std::set<int> &available,
- std::map<int, std::vector<std::pair<int, int>>>
- *minimum) = 0;
+ std::map<int, std::vector<std::pair<int, int>>> *minimum) = 0;
/**
* Compute the smallest subset of **available** chunks that needs
erasures[erasures_count] = i;
erasures_count++;
}
- if (i < k)
+ if (i < k) {
data[i] = (*decoded)[i].c_str();
- else
+ } else {
coding[i - k] = (*decoded)[i].c_str();
+ }
}
erasures[erasures_count] = -1;
ceph_assert(erasures_count > 0);
uint64_t size = 0;
for (auto &&[shard, ptr] : in) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
+ }
chunks[static_cast<int>(shard)] = const_cast<char*>(ptr.c_str());
}
for (auto &&[shard, ptr] : out) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
+ }
chunks[static_cast<int>(shard)] = ptr.c_str();
}
char *zeros = nullptr;
for (shard_id_t i; i < k + m; ++i) {
- if (in.contains(i) || out.contains(i)) continue;
+ if (in.contains(i) || out.contains(i)) {
+ continue;
+ }
if (zeros == nullptr) {
zeros = (char*)malloc(size);
isa_encode(&chunks[0], &chunks[k], size);
- if (zeros != nullptr) free(zeros);
+ if (zeros != nullptr) {
+ free(zeros);
+ }
return 0;
}
int ErasureCodeIsa::decode_chunks(const shard_id_set &want_to_read,
shard_id_map<bufferptr> &in,
- shard_id_map<bufferptr> &out)
+ shard_id_map<bufferptr> &out)
{
unsigned int size = 0;
shard_id_set erasures_set;
memset(coding, 0, sizeof(char*) * m);
for (auto &&[shard, ptr] : in) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
- if (shard < k) {
- data[static_cast<int>(shard)] = const_cast<char*>(ptr.c_str());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
}
- else {
- coding[static_cast<int>(shard) - k] = const_cast<char*>(ptr.c_str());
+
+ if (shard < k) {
+ data[static_cast<int>(shard)] = ptr.c_str();
+ } else {
+ coding[static_cast<int>(shard) - k] = ptr.c_str();
}
erasures_set.erase(shard);
}
for (auto &&[shard, ptr] : out) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
- if (shard < k) {
- data[static_cast<int>(shard)] = const_cast<char*>(ptr.c_str());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
}
- else {
- coding[static_cast<int>(shard) - k] = const_cast<char*>(ptr.c_str());
+
+ if (shard < k) {
+ data[static_cast<int>(shard)] = ptr.c_str();
+ } else {
+ coding[static_cast<int>(shard) - k] = ptr.c_str();
}
+ erasures_set.insert(shard);
}
for (int i = 0; i < k + m; i++) {
char **buf = i < k ? &data[i] : &coding[i - k];
if (*buf == nullptr) {
*buf = (char *)malloc(size);
+ ceph_assert(buf != nullptr);
to_free.insert(shard_id_t(i));
+ /* If buffer was not provided, is not an erasure (i.e. in the out map),
+ * and a data shard, then it can be assumed to be zero. This is most
+ * likely due to EC shards being different sizes.
+ */
+ if (i < k && !erasures_set.contains(shard_id_t(i))) {
+ memset(*buf, 0, size);
+ }
}
}
ErasureCodeIsa::isa_xor(char **data, char *coding, int blocksize, int data_vectors)
{
ceph_assert(data_vectors <= MAX_K);
- char * xor_bufs[MAX_K + 1];
+ char *xor_bufs[MAX_K + 1];
for (int i = 0; i < data_vectors; i++) {
xor_bufs[i] = data[i];
}
// Otherwise, use byte_xor()
bool aligned = true;
for (int i = 0; i <= data_vectors; i++) {
- aligned &= is_aligned(xor_bufs[i], EC_ISA_ADDRESS_ALIGNMENT);
+ if (!is_aligned(xor_bufs[i], EC_ISA_ADDRESS_ALIGNMENT)) {
+ aligned = false;
+ break;
+ }
}
if (aligned) {
const bufferptr &new_data,
bufferptr *delta_maybe_in_place)
{
- constexpr int data_vectors = 2;
- char * data[data_vectors];
+ constexpr int NUM_DATA_VECTORS = 2;
+ char * data[NUM_DATA_VECTORS];
data[0] = const_cast<char*>(old_data.c_str());
data[1] = const_cast<char*>(new_data.c_str());
char * coding = delta_maybe_in_place->c_str();
- isa_xor(data, coding, delta_maybe_in_place->length(), data_vectors);
+ isa_xor(data, coding, delta_maybe_in_place->length(), NUM_DATA_VECTORS);
}
// -----------------------------------------------------------------------------
const unsigned blocksize = first->second.length();
for (auto const& [datashard, databuf] : in) {
- if (datashard < k) {
- for (auto const& [codingshard, codingbuf] : out) {
- if (codingshard >= k) {
- ceph_assert(codingbuf.length() == blocksize);
- if (m==1) {
- constexpr int data_vectors = 2;
- char * data[data_vectors];
- data[0] = const_cast<char*>(databuf.c_str());
- data[1] = const_cast<char*>(codingbuf.c_str());
- char * coding = const_cast<char*>(codingbuf.c_str());
- isa_xor(data, coding, blocksize, data_vectors);
- } else {
- unsigned char* data = reinterpret_cast<unsigned char*>(const_cast<char*>(databuf.c_str()));
- unsigned char* coding = reinterpret_cast<unsigned char*>(const_cast<char*>(codingbuf.c_str()));
- ec_encode_data_update(blocksize, k, 1, static_cast<int>(datashard), encode_tbls + (32 * k * (static_cast<int>(codingshard) - k)), data, &coding);
- }
- }
+ if (datashard >= k) {
+ continue;
+ }
+ for (auto const& [codingshard, codingbuf] : out) {
+ if (codingshard < k) {
+ continue;
+ }
+ ceph_assert(codingbuf.length() == blocksize);
+ if (m == 1) {
+ constexpr int NUM_DATA_VECTORS = 2;
+ char * data[NUM_DATA_VECTORS];
+ data[0] = const_cast<char*>(databuf.c_str());
+ data[1] = codingbuf.c_str();
+ char * coding = codingbuf.c_str();
+ isa_xor(data, coding, blocksize, NUM_DATA_VECTORS);
+ } else {
+ unsigned char* data = reinterpret_cast<unsigned char*>(const_cast<char*>(databuf.c_str()));
+ unsigned char* coding = reinterpret_cast<unsigned char*>(codingbuf.c_str());
+ // We always update one parity at a time, so specify 1 row, and a pointer to the
+ // correct row in encode_tbls for this particular parity
+ ec_encode_data_update(blocksize, k, 1, static_cast<int>(datashard),
+ encode_tbls + (32 * k * (static_cast<int>(codingshard) - k)),
+ data, &coding);
}
}
}
uint64_t size = 0;
for (auto &&[shard, ptr] : in) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
+ }
chunks[static_cast<int>(shard)] = const_cast<char*>(ptr.c_str());
}
for (auto &&[shard, ptr] : out) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
+ }
chunks[static_cast<int>(shard)] = ptr.c_str();
}
erasures[erasures_count] = i;
erasures_count++;
}
- if (i < k)
+ if (i < k) {
data[i] = (*decoded)[i].c_str();
- else
+ } else {
coding[i - k] = (*decoded)[i].c_str();
+ }
}
erasures[erasures_count] = -1;
else ceph_assert(size == ptr.length());
if (shard < k) {
data[static_cast<int>(shard)] = const_cast<char*>(ptr.c_str());
- }
- else {
+ } else {
coding[static_cast<int>(shard) - k] = const_cast<char*>(ptr.c_str());
}
erasures_set.erase(shard);
else ceph_assert(size == ptr.length());
if (shard < k) {
data[static_cast<int>(shard)] = const_cast<char*>(ptr.c_str());
- }
- else {
+ } else {
coding[static_cast<int>(shard) - k] = const_cast<char*>(ptr.c_str());
}
+ erasures_set.insert(shard);
}
for (int i = 0; i < k + m; i++) {
if (*buf == nullptr) {
*buf = (char *)malloc(size);
to_free.insert(shard_id_t(i));
+ /* If we are inventing a buffer for non-erasure shard, its zeros! */
+ if (i < k && !erasures_set.contains(shard_id_t(i))) {
+ memset(*buf, 0, size);
+ }
}
}
for (auto && shard : erasures_set) {
erasures[erasures_count++] = static_cast<int>(shard);
}
-
-
erasures[erasures_count] = -1;
ceph_assert(erasures_count > 0);
+
int r = jerasure_decode(erasures, data, coding, size);
for (auto & shard : to_free) {
int i = static_cast<int>(shard);
const unsigned blocksize = first->second.length();
for (auto const& [datashard, databuf] : in) {
- if (datashard < k) {
- for (auto const& [codingshard, codingbuf] : out) {
- if (codingshard >= k) {
- ceph_assert(codingbuf.length() == blocksize);
- char* input_data = const_cast<char*>(databuf.c_str());
- char* output_data = const_cast<char*>(codingbuf.c_str());
- if (static_cast<int>(codingshard) == k) {
- galois_region_xor(input_data, output_data, blocksize);
- }
- else {
- switch (w) {
- case 8:
- galois_w08_region_multiply(input_data, matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))], blocksize, output_data, 1);
- break;
- case 16:
- galois_w16_region_multiply(input_data, matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))], blocksize, output_data, 1);
- break;
- case 32:
- galois_w32_region_multiply(input_data, matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))], blocksize, output_data, 1);
- break;
- }
- }
+ if (datashard >= k) {
+ continue;
+ }
+ for (auto const& [codingshard, codingbuf] : out) {
+ if (codingshard < k) {
+ continue;
+ }
+ ceph_assert(codingbuf.length() == blocksize);
+ char* input_data = const_cast<char*>(databuf.c_str());
+ char* output_data = const_cast<char*>(codingbuf.c_str());
+ if (static_cast<int>(codingshard) == k) {
+ galois_region_xor(input_data, output_data, blocksize);
+ } else {
+ switch (w) {
+ // We always update one parity at a time, so specify the correct row
+ // in the matrix for this particular parity
+ case 8:
+ galois_w08_region_multiply(
+ input_data,
+ matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))],
+ blocksize, output_data, 1);
+ break;
+ case 16:
+ galois_w16_region_multiply(
+ input_data,
+ matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))],
+ blocksize, output_data, 1);
+ break;
+ case 32:
+ galois_w32_region_multiply(
+ input_data,
+ matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))],
+ blocksize, output_data, 1);
+ break;
}
}
}
unsigned int blocksize = first->second.length();
for (auto const& [datashard, databuf] : in) {
- if (datashard < k) {
- for (auto const& [codingshard, codingbuf] : out) {
- if (codingshard >= k) {
- ceph_assert(codingbuf.length() == blocksize);
- char * ptr_copy[2];
- ptr_copy[0] = const_cast<char*>(databuf.c_str());
- ptr_copy[1] = const_cast<char*>(codingbuf.c_str());
- unsigned int done;
- for (done = 0; done < blocksize; done += (packetsize*w)) {
- do_scheduled_ops(ptr_copy, simple_schedule, packetsize, static_cast<int>(datashard), static_cast<int>(codingshard));
- ptr_copy[0] += (packetsize*w);
- ptr_copy[1] += (packetsize*w);
- }
- }
+ if (datashard >= k) {
+ continue;
+ }
+ for (auto const& [codingshard, codingbuf] : out) {
+ if (codingshard < k) {
+ continue;
+ }
+ ceph_assert(codingbuf.length() == blocksize);
+ char * ptr_copy[2];
+ ptr_copy[0] = const_cast<char*>(databuf.c_str());
+ ptr_copy[1] = codingbuf.c_str();
+ unsigned int done;
+ for (done = 0; done < blocksize; done += (packetsize*w)) {
+ do_scheduled_ops(ptr_copy, simple_schedule, packetsize,
+ static_cast<int>(datashard), static_cast<int>(codingshard));
+ ptr_copy[0] += (packetsize*w);
+ ptr_copy[1] += (packetsize*w);
}
}
}
int blocksize)
{
return jerasure_matrix_decode(k, m, w, matrix, 1,
- erasures, data, coding, blocksize);
+ erasures, data, coding, blocksize);
}
void ErasureCodeJerasureReedSolomonVandermonde::apply_delta(const shard_id_map<bufferptr> &in,
}
int ErasureCodeJerasureReedSolomonRAID6::jerasure_decode(int *erasures,
- char **data,
- char **coding,
- int blocksize)
+ char **data,
+ char **coding,
+ int blocksize)
{
return jerasure_matrix_decode(k, m, w, matrix, 1, erasures, data, coding, blocksize);
}
// ErasureCodeJerasureCauchy
//
void ErasureCodeJerasureCauchy::jerasure_encode(char **data,
- char **coding,
- int blocksize)
+ char **coding,
+ int blocksize)
{
jerasure_schedule_encode(k, m, w, schedule,
- data, coding, blocksize, packetsize);
+ data, coding, blocksize, packetsize);
}
int ErasureCodeJerasureCauchy::jerasure_decode(int *erasures,
- char **data,
- char **coding,
- int blocksize)
+ char **data,
+ char **coding,
+ int blocksize)
{
return jerasure_schedule_decode_lazy(k, m, w, bitmatrix,
- erasures, data, coding, blocksize, packetsize, 1);
+ erasures, data, coding, blocksize, packetsize, 1);
}
void ErasureCodeJerasureCauchy::apply_delta(const shard_id_map<bufferptr> &in,
if ( ((w*packetsize*sizeof(int))%LARGEST_VECTOR_WORDSIZE) )
alignment = k*w*packetsize*LARGEST_VECTOR_WORDSIZE;
return alignment;
- }
+ }
}
int ErasureCodeJerasureCauchy::parse(ErasureCodeProfile &profile,
simple_schedule = jerasure_dumb_bitmatrix_to_schedule(k, m, w, bitmatrix);
}
-ErasureCodeJerasureCauchy::~ErasureCodeJerasureCauchy()
+ErasureCodeJerasureCauchy::~ErasureCodeJerasureCauchy()
{
if (bitmatrix)
free(bitmatrix);
int blocksize)
{
jerasure_schedule_encode(k, m, w, schedule, data,
- coding, blocksize, packetsize);
+ coding, blocksize, packetsize);
}
int ErasureCodeJerasureLiberation::jerasure_decode(int *erasures,
int blocksize)
{
return jerasure_schedule_decode_lazy(k, m, w, bitmatrix, erasures, data,
- coding, blocksize, packetsize, 1);
+ coding, blocksize, packetsize, 1);
}
void ErasureCodeJerasureLiberation::apply_delta(const shard_id_map<bufferptr> &in,
ceph::bufferptr *delta_maybe_in_place);
void apply_delta(const shard_id_map<ceph::bufferptr> &in,
- shard_id_map<ceph::bufferptr> &out) = 0;
+ shard_id_map<ceph::bufferptr> &out) = 0;
int init(ceph::ErasureCodeProfile &profile, std::ostream *ss) override;
}
for (const auto& [shard, ptr] : out) {
- if (chunk_size == 0) chunk_size = ptr.length();
- else ceph_assert(chunk_size == ptr.length());
+ if (chunk_size == 0) {
+ chunk_size = ptr.length();
+ } else {
+ ceph_assert(chunk_size == ptr.length());
+ }
erasures.insert(shard);
}
{
shard_id_t cs(*c);
if (!erasures.contains(cs)) {
- if (in.contains(cs)) layer_in[j] = in[cs];
- else layer_in[j] = out[cs];
- }
- else {
+ if (in.contains(cs)) {
+ layer_in[j] = in[cs];
+ } else {
+ layer_in[j] = out[cs];
+ }
+ } else {
layer_out[j] = out[cs];
}
++j;
uint64_t size = 0;
for (auto &&[shard, ptr] : in) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
+ }
chunks[static_cast<int>(shard)] = const_cast<char*>(ptr.c_str());
}
for (auto &&[shard, ptr] : out) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
+ }
chunks[static_cast<int>(shard)] = ptr.c_str();
}
int ErasureCodeShec::decode_chunks(const shard_id_set &want_to_read,
shard_id_map<bufferptr> &in,
- shard_id_map<bufferptr> &out)
+ shard_id_map<bufferptr> &out)
{
unsigned int size = 0;
int erased[k + m];
char *coding[m];
for (auto &&[shard, ptr] : in) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
+ }
+
if (shard < k) {
data[static_cast<int>(shard)] = ptr.c_str();
- }
- else {
+ } else {
coding[static_cast<int>(shard) - k] = ptr.c_str();
}
avails[static_cast<int>(shard)] = 1;
}
for (auto &&[shard, ptr] : out) {
- if (size == 0) size = ptr.length();
- else ceph_assert(size == ptr.length());
+ if (size == 0) {
+ size = ptr.length();
+ } else {
+ ceph_assert(size == ptr.length());
+ }
+
if (shard < k) {
data[static_cast<int>(shard)] = ptr.c_str();
- }
- else {
+ } else {
coding[static_cast<int>(shard) - k] = ptr.c_str();
}
avails[static_cast<int>(shard)] = 0;
if (want_to_read.count(shard) > 0) {
erased[static_cast<int>(shard)] = 1;
erased_count++;
- }
- else {
+ } else {
erased[static_cast<int>(shard)] = 0;
}
}
const unsigned blocksize = first->second.length();
for (auto const& [datashard, databuf] : in) {
- if (datashard < k) {
- for (auto const& [codingshard, codingbuf] : out) {
- if (codingshard >= k) {
- ceph_assert(codingbuf.length() == blocksize);
- char* input_data = const_cast<char*>(databuf.c_str());
- char* output_data = const_cast<char*>(codingbuf.c_str());
- switch (w) {
- case 8:
- galois_w08_region_multiply(input_data, matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))], blocksize, output_data, 1);
- break;
- case 16:
- galois_w16_region_multiply(input_data, matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))], blocksize, output_data, 1);
- break;
- case 32:
- galois_w32_region_multiply(input_data, matrix[static_cast<int>(datashard) + (k * (int(codingshard) - k))], blocksize, output_data, 1);
- break;
- }
- }
+ if (datashard >= k) {
+ continue;
+ }
+ for (auto const& [codingshard, codingbuf] : out) {
+ if (codingshard < k) {
+ continue;
+ }
+ ceph_assert(codingbuf.length() == blocksize);
+ char* input_data = const_cast<char*>(databuf.c_str());
+ char* output_data = codingbuf.c_str();
+ switch (w) {
+ // We always update one parity at a time, so specify the correct row
+ // in the matrix for this particular parity
+ case 8:
+ galois_w08_region_multiply(
+ input_data,
+ matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))],
+ blocksize, output_data, 1);
+ break;
+ case 16:
+ galois_w16_region_multiply(
+ input_data,
+ matrix[static_cast<int>(datashard) + (k * (static_cast<int>(codingshard) - k))],
+ blocksize, output_data, 1);
+ break;
+ case 32:
+ galois_w32_region_multiply(
+ input_data,
+ matrix[static_cast<int>(datashard) + (k * (int(codingshard) - k))],
+ blocksize, output_data, 1);
+ break;
}
}
}
const static raw_shard_id_t NO_SHARD;
- void encode(ceph::buffer::list &bl) const {
- using ceph::encode;
- encode(id, bl);
- }
- void decode(ceph::buffer::list::const_iterator &bl) {
- using ceph::decode;
- decode(id, bl);
- }
void dump(ceph::Formatter *f) const {
f->dump_int("id", id);
}
unsigned int chunk_length = get_chunk_size(in.length());
bufferlist out(in);
unsigned int width = get_chunk_count() * get_chunk_size(in.length());
- bufferptr pad(width - in.length());
- pad.zero(0, get_data_chunk_count());
- out.push_back(pad);
+ out.append_zero(width - in.length());
//
// compute the coding chunk with first chunk ^ second chunk
//