From 9f9d1482868e8e1044790c8358893f4421d89692 Mon Sep 17 00:00:00 2001 From: Xavier Hernandez Date: Tue, 14 Feb 2017 11:12:58 +0100 Subject: cluster/ec: Fallback to precompiled code When dynamic code generation fails for some reason, instead of causing a failure in encode/decode, fallback to the precompiled version. Change-Id: I4f8a97d3033aa5885779722b19c6e611caa4ffea BUG: 1421955 Signed-off-by: Xavier Hernandez Reviewed-on: https://review.gluster.org/16614 Smoke: Gluster Build System NetBSD-regression: NetBSD Build System Reviewed-by: Niels de Vos CentOS-regression: Gluster Build System Reviewed-by: Pranith Kumar Karampuri --- xlators/cluster/ec/src/ec-code.c | 99 +++++++++++++++++++++++--------------- xlators/cluster/ec/src/ec-method.c | 32 ++---------- xlators/cluster/ec/src/ec-types.h | 2 - 3 files changed, 63 insertions(+), 70 deletions(-) diff --git a/xlators/cluster/ec/src/ec-code.c b/xlators/cluster/ec/src/ec-code.c index 25a501e61b7..7b5d53d0a37 100644 --- a/xlators/cluster/ec/src/ec-code.c +++ b/xlators/cluster/ec/src/ec-code.c @@ -679,11 +679,6 @@ ec_code_create(ec_gf_t *gf, ec_code_gen_t *gen) code->gf = gf; code->gen = gen; - if (gen == NULL) { - code->width = sizeof(uint64_t); - } else { - code->width = gen->width; - } return code; } @@ -716,46 +711,71 @@ ec_code_value_next(uint32_t *values, uint32_t count, uint32_t *offset) return next; } +static void * +ec_code_build_dynamic(ec_code_t *code, uint32_t width, uint32_t *values, + uint32_t count, gf_boolean_t linear) +{ + ec_code_builder_t *builder; + uint32_t offset, val, next; + + builder = ec_code_prepare(code, count, width, linear); + if (EC_IS_ERR(builder)) { + return builder; + } + + offset = -1; + next = ec_code_value_next(values, count, &offset); + if (next != 0) { + ec_code_gf_load(builder, offset); + do { + val = next; + next = ec_code_value_next(values, count, &offset); + if (next != 0) { + ec_code_gf_mul(builder, ec_gf_div(code->gf, + val, next)); + ec_code_gf_load_xor(builder, offset); + } + } while (next != 0); + ec_code_gf_mul(builder, val); + ec_code_gf_store(builder); + } else { + ec_code_gf_clear(builder); + } + + return ec_code_compile(builder); +} + static void * ec_code_build(ec_code_t *code, uint32_t width, uint32_t *values, uint32_t count, gf_boolean_t linear) { - ec_code_builder_t *builder; - uint32_t offset, val, next; + void *func; - if (code->gen == NULL) { - ec_code_c_prepare(code->gf, values, count); - if (linear) { - return ec_code_c_linear; - } else { - return ec_code_c_interleaved; + if (code->gen != NULL) { + func = ec_code_build_dynamic(code, width, values, count, + linear); + if (!EC_IS_ERR(func)) { + return func; + } + + gf_msg_debug(THIS->name, GF_LOG_DEBUG, + "Unable to generate dynamic code. Falling back " + "to precompiled code"); + + /* The dynamic code generation shouldn't fail in normal + * conditions, but if it fails at some point, it's very + * probable that it will fail again, so we completely disable + * dynamic code generation. */ + code->gen = NULL; } - } - builder = ec_code_prepare(code, count, width, linear); - if (EC_IS_ERR(builder)) { - return builder; - } + ec_code_c_prepare(code->gf, values, count); - offset = -1; - next = ec_code_value_next(values, count, &offset); - if (next != 0) { - ec_code_gf_load(builder, offset); - do { - val = next; - next = ec_code_value_next(values, count, &offset); - if (next != 0) { - ec_code_gf_mul(builder, ec_gf_div(code->gf, val, next)); - ec_code_gf_load_xor(builder, offset); - } - } while (next != 0); - ec_code_gf_mul(builder, val); - ec_code_gf_store(builder); - } else { - ec_code_gf_clear(builder); - } + if (linear) { + return ec_code_c_linear; + } - return ec_code_compile(builder); + return ec_code_c_interleaved; } ec_code_func_linear_t @@ -777,9 +797,10 @@ ec_code_build_interleaved(ec_code_t *code, uint32_t width, uint32_t *values, void ec_code_release(ec_code_t *code, ec_code_func_t *func) { - if (code->gen != NULL) { - ec_code_free(ec_code_chunk_from_func(func->linear)); - } + if ((func->linear != ec_code_c_linear) && + (func->interleaved != ec_code_c_interleaved)) { + ec_code_free(ec_code_chunk_from_func(func->linear)); + } } void diff --git a/xlators/cluster/ec/src/ec-method.c b/xlators/cluster/ec/src/ec-method.c index 41bf0406ecb..e0dd8e7f1a0 100644 --- a/xlators/cluster/ec/src/ec-method.c +++ b/xlators/cluster/ec/src/ec-method.c @@ -70,12 +70,11 @@ ec_method_matrix_inverse(ec_gf_t *gf, uint32_t *matrix, uint32_t *values, } } -static int32_t +static void ec_method_matrix_init(ec_matrix_list_t *list, ec_matrix_t *matrix, uintptr_t mask, uint32_t *rows, gf_boolean_t inverse) { uint32_t i; - int32_t err = 0; matrix->refs = 1; matrix->mask = mask; @@ -94,11 +93,6 @@ ec_method_matrix_init(ec_matrix_list_t *list, ec_matrix_t *matrix, EC_METHOD_WORD_SIZE, matrix->row_data[i].values, matrix->columns); - if (EC_IS_ERR(matrix->row_data[i].func.interleaved)) { - err = EC_GET_ERR(matrix->row_data[i].func.interleaved); - matrix->row_data[i].func.interleaved = NULL; - break; - } } } else { matrix->rows = list->rows; @@ -110,15 +104,8 @@ ec_method_matrix_init(ec_matrix_list_t *list, ec_matrix_t *matrix, ec_code_build_linear(matrix->code, EC_METHOD_WORD_SIZE, matrix->row_data[i].values, matrix->columns); - if (EC_IS_ERR(matrix->row_data[i].func.linear)) { - err = EC_GET_ERR(matrix->row_data[i].func.linear); - matrix->row_data[i].func.linear = NULL; - break; - } } } - - return err; } static void @@ -218,7 +205,6 @@ ec_method_matrix_get(ec_matrix_list_t *list, uintptr_t mask, uint32_t *rows) { ec_matrix_t *matrix; uint32_t pos; - int32_t err = 0; LOCK(&list->lock); @@ -247,13 +233,7 @@ ec_method_matrix_get(ec_matrix_list_t *list, uintptr_t mask, uint32_t *rows) sizeof(ec_matrix_row_t) * list->columns); } - err = ec_method_matrix_init(list, matrix, mask, rows, _gf_true); - if (err != 0) { - ec_method_matrix_unref(list, matrix); - matrix = EC_ERR(err); - - goto out; - } + ec_method_matrix_init(list, matrix, mask, rows, _gf_true); if (list->count < list->max) { ec_method_matrix_insert(list, matrix); @@ -303,22 +283,16 @@ ec_method_setup(xlator_t *xl, ec_matrix_list_t *list, const char *gen) list->code = NULL; goto failed_matrix; } - list->width = list->code->width; for (i = 0; i < list->rows; i++) { values[i] = i + 1; } - err = ec_method_matrix_init(list, matrix, 0, values, _gf_false); - if (err != 0) { - goto failed_code; - } + ec_method_matrix_init(list, matrix, 0, values, _gf_false); list->encode = matrix; return 0; -failed_code: - ec_code_destroy(list->code); failed_matrix: GF_FREE(matrix); failed: diff --git a/xlators/cluster/ec/src/ec-types.h b/xlators/cluster/ec/src/ec-types.h index 751652c20b1..d701fe7d25e 100644 --- a/xlators/cluster/ec/src/ec-types.h +++ b/xlators/cluster/ec/src/ec-types.h @@ -408,7 +408,6 @@ struct _ec_code_gen { struct _ec_code { gf_lock_t lock; struct list_head spaces; - uint32_t width; ec_gf_t *gf; ec_code_gen_t *gen; }; @@ -484,7 +483,6 @@ struct _ec_matrix_list { uint32_t rows; uint32_t max; uint32_t count; - uint32_t width; uint32_t stripe; struct mem_pool *pool; ec_gf_t *gf; -- cgit