diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | doc/Makefile.am | 4 | ||||
-rw-r--r-- | include/erasurecode/erasurecode.h | 10 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/erasurecode.c | 59 | ||||
-rw-r--r-- | test/libec_slap.c | 12 | ||||
-rw-r--r-- | test/liberasurecode_test.c | 41 |
8 files changed, 102 insertions, 42 deletions
@@ -51,8 +51,13 @@ compile cscope.files install-sh libtool +ltmain.sh +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltversion.m4 # doxygen documentation ^doc/.*\.doxytag ^doc/html +^doc/latex *doxygen.cfg @@ -178,17 +178,16 @@ int liberasurecode_encode_cleanup(int desc, char **encoded_data, * @param fragments - erasure encoded fragments (> = k)
* @param num_fragments - number of fragments being passed in
* @param fragment_len - length of each fragment (assume they are the same)
+ * @param force_metadata_checks - force fragment metadata checks (default: 0)
* @param out_data - _output_ pointer to decoded data
* @param out_data_len - _output_ length of decoded output
- * (both output data pointers are allocated by liberasurecode,
- * caller invokes liberasurecode_decode_clean() after it has
- * read decoded data in 'out_data')
*
* @return 0 on success, -error code otherwise
*/
int liberasurecode_decode(int desc,
char **available_fragments, /* input */
int num_fragments, uint64_t fragment_len, /* input */
+ int force_metadata_checks, /* input */
char **out_data, uint64_t *out_data_len); /* output */
/**
@@ -420,4 +419,4 @@ Code organization |-- INSTALL
+-- ChangeLog
```
----
\ No newline at end of file +---
diff --git a/doc/Makefile.am b/doc/Makefile.am index aea521f..31804cb 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -16,14 +16,14 @@ clean-local: rm -rf html install-data-local: html - $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR) + ../install-sh -d $(DESTDIR)$(TARGET_DIR) (installfiles=`echo html/*`; \ if test "$$installfiles" = 'html/*'; \ then echo '-- Nothing to install' ; \ else \ for i in $$installfiles; do \ echo '-- Installing '$$i ; \ - $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \ + ../install-sh $$i $(DESTDIR)$(TARGET_DIR); \ done; \ fi) diff --git a/include/erasurecode/erasurecode.h b/include/erasurecode/erasurecode.h index e8ad056..74f6385 100644 --- a/include/erasurecode/erasurecode.h +++ b/include/erasurecode/erasurecode.h @@ -169,6 +169,7 @@ int liberasurecode_encode_cleanup(int desc, char **encoded_data, * @param fragments - erasure encoded fragments (> = k) * @param num_fragments - number of fragments being passed in * @param fragment_len - length of each fragment (assume they are the same) + * @param force_metadata_checks - force fragment metadata checks (default: 0) * @param out_data - _output_ pointer to decoded data * @param out_data_len - _output_ length of decoded output * (both output data pointers are allocated by liberasurecode, @@ -180,6 +181,7 @@ int liberasurecode_encode_cleanup(int desc, char **encoded_data, int liberasurecode_decode(int desc, char **available_fragments, /* input */ int num_fragments, uint64_t fragment_len, /* input */ + int force_metadata_checks, /* input */ char **out_data, uint64_t *out_data_len); /* output */ /** @@ -279,9 +281,9 @@ int liberasurecode_get_fragment_metadata(char *fragment, * from liberasurecode_instance_create() * @param fragment - fragment to verify * -* @return 0 if fragment validation is successful, 1 otherwise. +* @return 1 if fragment validation fails, 0 otherwise. */ -int is_valid_fragment(int desc, char *fragment); +int is_invalid_fragment(int desc, char *fragment); /** * Verify a subset of fragments generated by encode() @@ -333,6 +335,10 @@ typedef enum { EBACKENDINITERR = 202, EBACKENDINUSE = 203, EBACKENDNOTAVAIL = 204, + EBADCHKSUM = 205, + EINVALIDPARAMS = 206, + EBADHEADER = 207, + EINSUFFFRAGS = 208, } LIBERASURECODE_ERROR_CODES; /* =~=*=~==~=*=~==~=*=~==~=*=~===~=*=~==~=*=~===~=*=~==~=*=~===~=*=~==~=*=~= */ diff --git a/src/Makefile.am b/src/Makefile.am index c6c2a21..ce6ef50 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -20,6 +20,12 @@ liberasurecode_la_SOURCES = \ backends/jerasure/jerasure_rs_cauchy.c \ backends/isa-l/isa_l_vand.c +# Install additional header files +liberasurecodeincludedir = $(includedir) +liberasurecodeinclude_HEADERS = \ + ../include/erasurecode/erasurecode.h \ + ../include/erasurecode/erasurecode_helpers.h + liberasurecode_la_CPPFLAGS = -Werror @GCOV_FLAGS@ liberasurecode_la_LIBADD = \ builtin/xor_codes/libXorcode.la -lpthread -lm @GCOV_LDFLAGS@ diff --git a/src/erasurecode.c b/src/erasurecode.c index 64381e7..8272f3e 100644 --- a/src/erasurecode.c +++ b/src/erasurecode.c @@ -495,6 +495,7 @@ int liberasurecode_decode_cleanup(int desc, char *data) * @param fragments - erasure encoded fragments (> = k) * @param num_fragments - number of fragments being passed in * @param fragment_len - length of each fragment (assume they are the same) + * @param force_metadata_checks - force fragment metadata checks (default: 0) * @param out_data - _output_ pointer to decoded data * @param out_data_len - _output_ length of decoded output * @return 0 on success, -error code otherwise @@ -502,6 +503,7 @@ int liberasurecode_decode_cleanup(int desc, char *data) int liberasurecode_decode(int desc, char **available_fragments, /* input */ int num_fragments, uint64_t fragment_len, /* input */ + int force_metadata_checks, /* input */ char **out_data, uint64_t *out_data_len) /* output */ { int i, j; @@ -546,6 +548,11 @@ int liberasurecode_decode(int desc, k = instance->args.uargs.k; m = instance->args.uargs.m; + if (num_fragments < k) { + ret = -EINSUFFFRAGS; + goto out; + } + /* * Try to re-assebmle the original data before attempting a decode */ @@ -578,6 +585,21 @@ int liberasurecode_decode(int desc, log_error("Could not allocate missing_idxs buffer!"); goto out; } + + /* If metadata checks requested, check fragment integrity upfront */ + if (force_metadata_checks) { + int num_invalid_fragments = 0; + for (i = 0; i < num_fragments; ++i) { + if (is_invalid_fragment(desc, available_fragments[i])) { + ++num_invalid_fragments; + } + } + if (num_invalid_fragments > (k - 1)) { + ret = -EINSUFFFRAGS; + log_error("Not enough valid fragments available for decode!"); + goto out; + } + } /* * Separate the fragments into data and parity. Also determine which @@ -937,6 +959,8 @@ int liberasurecode_get_fragment_metadata(char *fragment, computed_chksum = crc32(0, fragment_data, fragment_size); if (stored_chksum != computed_chksum) { fragment_metadata->chksum_mismatch = 1; + } else { + fragment_metadata->chksum_mismatch = 0; } break; } @@ -963,13 +987,13 @@ int liberasurecode_verify_fragment_metadata(ec_backend_t be, return 0; } -int is_valid_fragment(int desc, char *fragment) +int is_invalid_fragment(int desc, char *fragment) { uint32_t ver = 0; fragment_metadata_t fragment_metadata; ec_backend_t be = liberasurecode_backend_instance_get_by_desc(desc); if (!be) { - log_error("Unable to verify stripe metadata: invalid backend id %d.", + log_error("Unable to verify fragment metadata: invalid backend id %d.", desc); return 1; } @@ -992,23 +1016,46 @@ int is_valid_fragment(int desc, char *fragment) return 0; } +int is_valid_fragment_metadata(int desc, fragment_metadata_t *fragment_metadata) +{ + ec_backend_t be = liberasurecode_backend_instance_get_by_desc(desc); + if (!be) { + log_error("Unable to verify stripe metadata: invalid backend id %d.", + desc); + return -EINVALIDPARAMS; + } + if (liberasurecode_verify_fragment_metadata(be, + fragment_metadata) != 0) { + return -EBADHEADER; + } + if (!be->common.ops->is_compatible_with(fragment_metadata->backend_version)) { + return -EBADHEADER; + } + if (fragment_metadata->chksum_mismatch == 1) { + return -EBADCHKSUM; + } + return 0; +} + int liberasurecode_verify_stripe_metadata(int desc, char **fragments, int num_fragments) { int i = 0; if (!fragments) { log_error("Unable to verify stripe metadata: fragments missing."); - return 1; + return -EINVALIDPARAMS; } if (num_fragments <= 0) { log_error("Unable to verify stripe metadata: " "number of fragments must be greater than 0."); - return 1; + return -EINVALIDPARAMS; } for (i = 0; i < num_fragments; i++) { - if (is_valid_fragment(desc, fragments[i]) == 1) { - return 1; + fragment_metadata_t *fragment_metadata = (fragment_metadata_t*)fragments[i]; + int ret = is_valid_fragment_metadata(desc, fragment_metadata); + if (ret < 0) { + return ret; } } diff --git a/test/libec_slap.c b/test/libec_slap.c index fb9e69a..0f3c24b 100644 --- a/test/libec_slap.c +++ b/test/libec_slap.c @@ -283,8 +283,8 @@ static int test_hd_code(struct ec_args *args, create_frags_array_set(&frags,encoded_data, args->k, encoded_parity, args->m, mask); rc = liberasurecode_decode(desc, frags.array, frags.num_fragments, - encoded_fragment_len, &out_data, - &out_data_len); + encoded_fragment_len, 1, + &out_data, &out_data_len); assert(rc == 0); assert(out_data_len == blocksize * args->k); if (memcmp(data, out_data, out_data_len) != 0) { @@ -308,15 +308,13 @@ static int test_hd_code(struct ec_args *args, create_frags_array_set(&frags,encoded_data, args->k, encoded_parity, args->m, mask); rc = liberasurecode_decode(desc, frags.array, frags.num_fragments, - encoded_fragment_len, &out_data, - &out_data_len); + encoded_fragment_len, 1, + &out_data, &out_data_len); free(frags.array); free(out_data); assert(rc == 0); - fprintf(stderr," Decode Scenario - "); - print_mask(mask); - fprintf(stderr,": OK\n"); + //print_mask(mask); } for (j = 0; j < args->k; j++) { free(encoded_data[j]); diff --git a/test/liberasurecode_test.c b/test/liberasurecode_test.c index 61492d1..b3c17df 100644 --- a/test/liberasurecode_test.c +++ b/test/liberasurecode_test.c @@ -346,23 +346,23 @@ static void test_decode_invalid_args() encoded_parity, &null_args, skips); rc = liberasurecode_decode(-1, avail_frags, num_avail_frags, - encoded_fragment_len, &decoded_data, - &decoded_data_len); + encoded_fragment_len, 1, + &decoded_data, &decoded_data_len); assert(rc < 0); rc = liberasurecode_decode(desc, NULL, num_avail_frags, - encoded_fragment_len, &decoded_data, - &decoded_data_len); + encoded_fragment_len, 1, + &decoded_data, &decoded_data_len); assert(rc < 0); rc = liberasurecode_decode(desc, avail_frags, num_avail_frags, - encoded_fragment_len, NULL, - &decoded_data_len); + encoded_fragment_len, 1, + NULL, &decoded_data_len); assert(rc < 0); rc = liberasurecode_decode(desc, avail_frags, num_avail_frags, - encoded_fragment_len, &decoded_data, - NULL); + encoded_fragment_len, 1, + &decoded_data, NULL); assert(rc < 0); free(skips); liberasurecode_encode_cleanup(desc, encoded_data, encoded_parity); @@ -470,19 +470,19 @@ static void test_verify_stripe_metadata_invalid_args() { char **frags = malloc(sizeof(char *) * num_frags); rc = liberasurecode_verify_stripe_metadata(desc, frags, num_frags); - assert(rc == 1); + assert(rc == -EINVALIDPARAMS); desc = liberasurecode_instance_create(EC_BACKEND_NULL, &null_args); assert(desc > 0); rc = liberasurecode_verify_stripe_metadata(desc, NULL, num_frags); - assert(rc == 1); + assert(rc == -EINVALIDPARAMS); rc = liberasurecode_verify_stripe_metadata(desc, frags, -1); - assert(rc == 1); + assert(rc == -EINVALIDPARAMS); rc = liberasurecode_verify_stripe_metadata(desc, frags, 0); - assert(rc == 1); + assert(rc == -EINVALIDPARAMS); } @@ -540,8 +540,8 @@ static void encode_decode_test_impl(const ec_backend_id_t be_id, assert(num_avail_frags != -1); rc = liberasurecode_decode(desc, avail_frags, num_avail_frags, - encoded_fragment_len, &decoded_data, - &decoded_data_len); + encoded_fragment_len, 1, + &decoded_data, &decoded_data_len); assert(0 == rc); assert(decoded_data_len == orig_data_size); assert(memcmp(decoded_data, orig_data, orig_data_size) == 0); @@ -952,7 +952,7 @@ static void test_verify_stripe_metadata(const ec_backend_id_t be_id, free(skip); } -static void verify_stripe_metadata_mismatch_impl(const ec_backend_id_t be_id, struct ec_args *args, +static void verify_fragment_metadata_mismatch_impl(const ec_backend_id_t be_id, struct ec_args *args, fragment_mismatch_scenario_t scenario) { int orig_data_size = 1024; @@ -1002,8 +1002,7 @@ static void verify_stripe_metadata_mismatch_impl(const ec_backend_id_t be_id, st default: assert(false); } - rc = liberasurecode_verify_stripe_metadata(desc, avail_frags, - num_avail_frags); + rc = is_invalid_fragment(desc, avail_frags[i]); assert(rc == 1); //heal fragment switch (scenario) { @@ -1030,25 +1029,25 @@ static void verify_stripe_metadata_mismatch_impl(const ec_backend_id_t be_id, st static void test_verify_stripe_metadata_libec_mismatch( const ec_backend_id_t be_id, struct ec_args *args) { - verify_stripe_metadata_mismatch_impl(be_id, args, LIBEC_VERSION_MISMATCH); + verify_fragment_metadata_mismatch_impl(be_id, args, LIBEC_VERSION_MISMATCH); } static void test_verify_stripe_metadata_magic_mismatch( const ec_backend_id_t be_id, struct ec_args *args) { - verify_stripe_metadata_mismatch_impl(be_id, args, MAGIC_MISMATCH); + verify_fragment_metadata_mismatch_impl(be_id, args, MAGIC_MISMATCH); } static void test_verify_stripe_metadata_be_id_mismatch( const ec_backend_id_t be_id, struct ec_args *args) { - verify_stripe_metadata_mismatch_impl(be_id, args, BACKEND_ID_MISMATCH); + verify_fragment_metadata_mismatch_impl(be_id, args, BACKEND_ID_MISMATCH); } static void test_verify_stripe_metadata_be_ver_mismatch( const ec_backend_id_t be_id, struct ec_args *args) { - verify_stripe_metadata_mismatch_impl(be_id, args, BACKEND_VERSION_MISMATCH); + verify_fragment_metadata_mismatch_impl(be_id, args, BACKEND_VERSION_MISMATCH); } |