Fix error handling on gf_ivnert_matrix in isa-l backend
Current isa-l has possibility to return corrupted decoded data or corrupted reconstructed data on decode/reconstruct without error code. That is from the specification of isa-l rs vandermond matrix discussed at [1]. With many # of parities cases, we may hit the case above due to failing to get the inverse matrix from the encode matrix. The isa-l maintener gbtucker suggests a good way to detect the failing inverse matrix, that we should handle the return value gf_invert_matrix. If gf_invert_matrix returns not 0, we should stop to decode/reconstruct and return failure return code to the caller immediately. Otherwise, the caller regards the garbage data/fragment as correct one. And this patch adds the specific test case we can hit the issue (it happens not so general). 1: https://github.com/01org/isa-l/issues/10 Related-Change: I6eb150d9d0c3febf233570fa7729f9f72df2e9be Change-Id: Icee788a0931fe692fe0de31fabc4ba450e338a87
This commit is contained in:
parent
b96cf4b2cc
commit
74eaa374c1
@ -261,7 +261,10 @@ static int isa_l_rs_vand_decode(void *desc, char **data, char **parity,
|
||||
goto out;
|
||||
}
|
||||
|
||||
isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, k);
|
||||
int im_ret = isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, k);
|
||||
if (im_ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Generate g_tbls from computed decode matrix (k x k) matrix
|
||||
g_tbls = malloc(sizeof(unsigned char) * (k * m * 32));
|
||||
@ -365,7 +368,10 @@ static int isa_l_rs_vand_reconstruct(void *desc, char **data, char **parity,
|
||||
goto out;
|
||||
}
|
||||
|
||||
isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, k);
|
||||
int im_ret = isa_l_desc->gf_invert_matrix(decode_matrix, decode_inverse, k);
|
||||
if (im_ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the row needed to reconstruct
|
||||
|
@ -1346,6 +1346,102 @@ static void test_decode_with_missing_multi_data_parity(
|
||||
}
|
||||
}
|
||||
|
||||
static void test_decode_reconstruct_specific_error_case(
|
||||
const ec_backend_id_t be_id, struct ec_args *args)
|
||||
{
|
||||
struct ec_args specific_1010_args = {
|
||||
.k = 10,
|
||||
.m = 10,
|
||||
};
|
||||
|
||||
int rc = 0;
|
||||
int desc = -1;
|
||||
int orig_data_size = 1024 * 1024;
|
||||
char *orig_data = create_buffer(orig_data_size, 'x');
|
||||
char **encoded_data = NULL, **encoded_parity = NULL;
|
||||
uint64_t encoded_fragment_len = 0;
|
||||
int num_avail_frags = -1;
|
||||
char **avail_frags = NULL;
|
||||
char *decoded_data = NULL;
|
||||
char *out_frag = NULL;
|
||||
uint64_t decoded_data_len = 0;
|
||||
|
||||
int *skips = create_skips_array(&specific_1010_args,-1);
|
||||
assert(skips != NULL);
|
||||
// available frags for a bad pattern: [0, 1, 2, 3, 4, 6, 7, 10, 12, 15]
|
||||
skips[5] = skips[8] = skips[9] = skips[11] = skips[13] = skips[14] =
|
||||
skips[16] = skips[17] = skips[18] = skips[19] = 1;
|
||||
|
||||
desc = liberasurecode_instance_create(
|
||||
EC_BACKEND_ISA_L_RS_VAND, &specific_1010_args);
|
||||
if (-EBACKENDNOTAVAIL == desc) {
|
||||
fprintf (stderr, "Backend library not available!\n");
|
||||
return;
|
||||
}
|
||||
assert(desc > 0);
|
||||
|
||||
rc = liberasurecode_encode(desc, orig_data, orig_data_size,
|
||||
&encoded_data, &encoded_parity, &encoded_fragment_len);
|
||||
assert(rc == 0);
|
||||
|
||||
num_avail_frags = create_frags_array(&avail_frags, encoded_data,
|
||||
encoded_parity, &specific_1010_args,
|
||||
skips);
|
||||
assert(num_avail_frags > 0);
|
||||
|
||||
rc = liberasurecode_decode(desc, avail_frags, num_avail_frags,
|
||||
encoded_fragment_len, 1,
|
||||
&decoded_data, &decoded_data_len);
|
||||
assert(rc == -1);
|
||||
free(avail_frags);
|
||||
|
||||
// 5 is a hole in available frags
|
||||
num_avail_frags = create_frags_array(&avail_frags, encoded_data,
|
||||
encoded_parity, &specific_1010_args,
|
||||
skips);
|
||||
out_frag = malloc(sizeof(char) * encoded_fragment_len);
|
||||
rc = liberasurecode_reconstruct_fragment(
|
||||
desc, avail_frags, 10, encoded_fragment_len, 5, out_frag);
|
||||
assert(rc == -1);
|
||||
|
||||
free(out_frag);
|
||||
free(avail_frags);
|
||||
|
||||
// sanity; [0, 1, 2, 3, 4, 6, 7, 10, 12, 14] is ok
|
||||
skips[15] = 1; skips[14] = 0;
|
||||
num_avail_frags = create_frags_array(&avail_frags, encoded_data,
|
||||
encoded_parity, &specific_1010_args,
|
||||
skips);
|
||||
assert(num_avail_frags > 0);
|
||||
rc = liberasurecode_decode(desc, avail_frags, num_avail_frags,
|
||||
encoded_fragment_len, 1,
|
||||
&decoded_data, &decoded_data_len);
|
||||
assert(rc == 0);
|
||||
// 5 is a hole in available frags
|
||||
out_frag = malloc(sizeof(char) * encoded_fragment_len);
|
||||
rc = liberasurecode_reconstruct_fragment(
|
||||
desc, avail_frags, 10, encoded_fragment_len, 5, out_frag);
|
||||
|
||||
assert(rc == 0);
|
||||
|
||||
free(out_frag);
|
||||
|
||||
// cleanup all
|
||||
rc = liberasurecode_encode_cleanup(desc, encoded_data, encoded_parity);
|
||||
assert(rc == 0);
|
||||
|
||||
rc = liberasurecode_decode_cleanup(desc, decoded_data);
|
||||
assert(rc == 0);
|
||||
|
||||
if (desc) {
|
||||
assert(0 == liberasurecode_instance_destroy(desc));
|
||||
}
|
||||
|
||||
free(orig_data);
|
||||
free(avail_frags);
|
||||
free(skips);
|
||||
}
|
||||
|
||||
static void test_simple_encode_decode(const ec_backend_id_t be_id,
|
||||
struct ec_args *args)
|
||||
{
|
||||
@ -1875,6 +1971,10 @@ struct testcase testcases[] = {
|
||||
test_verify_stripe_metadata_frag_idx_invalid,
|
||||
EC_BACKEND_ISA_L_RS_VAND, CHKSUM_CRC32,
|
||||
.skip = false},
|
||||
{"test_isa_l_decode_reconstruct_specific_error_case",
|
||||
test_decode_reconstruct_specific_error_case,
|
||||
EC_BACKENDS_MAX, 0, // note this test is using ISA-L in hard coded
|
||||
.skip = false},
|
||||
// shss tests
|
||||
{"create_and_destroy_backend",
|
||||
test_create_and_destroy_backend,
|
||||
|
Loading…
Reference in New Issue
Block a user