summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
Diffstat (limited to 'xlators')
-rw-r--r--xlators/cluster/ec/src/Makefile.am1
-rw-r--r--xlators/cluster/ec/src/ec-code.c221
-rw-r--r--xlators/cluster/ec/src/ec-galois.c9
-rw-r--r--xlators/cluster/ec/src/ec-helpers.h4
-rw-r--r--xlators/cluster/ec/src/ec-inode-read.c6
-rw-r--r--xlators/cluster/ec/src/ec-messages.h16
-rw-r--r--xlators/cluster/ec/src/ec-method.c69
-rw-r--r--xlators/cluster/ec/src/ec-method.h25
-rw-r--r--xlators/cluster/ec/src/ec-types.h3
-rw-r--r--xlators/cluster/ec/src/ec.c12
10 files changed, 272 insertions, 94 deletions
diff --git a/xlators/cluster/ec/src/Makefile.am b/xlators/cluster/ec/src/Makefile.am
index 0cd34b58f3c..406a636bbc2 100644
--- a/xlators/cluster/ec/src/Makefile.am
+++ b/xlators/cluster/ec/src/Makefile.am
@@ -70,6 +70,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/xlators/lib/src
AM_CPPFLAGS += -I$(top_srcdir)/rpc/rpc-lib/src
AM_CPPFLAGS += -I$(top_srcdir)/rpc/xdr/src
AM_CPPFLAGS += -I$(top_builddir)/rpc/xdr/src
+AM_CPPFLAGS += -DGLUSTERFS_LIBEXECDIR=\"$(GLUSTERFS_LIBEXECDIR)\"
AM_CFLAGS = -Wall $(GF_CFLAGS)
diff --git a/xlators/cluster/ec/src/ec-code.c b/xlators/cluster/ec/src/ec-code.c
index a1f652779f3..9647a08287c 100644
--- a/xlators/cluster/ec/src/ec-code.c
+++ b/xlators/cluster/ec/src/ec-code.c
@@ -20,6 +20,7 @@
#include "ec-code.h"
#include "ec-messages.h"
#include "ec-code-c.h"
+#include "ec-helpers.h"
#ifdef USE_EC_DYNAMIC_X64
#include "ec-code-x64.h"
@@ -33,6 +34,11 @@
#include "ec-code-avx.h"
#endif
+#define EC_CODE_SIZE (1024 * 64)
+#define EC_CODE_ALIGN 4096
+
+#define EC_CODE_CHUNK_MIN_SIZE 512
+
#define EC_PROC_BUFFER_SIZE 4096
#define PROC_CPUINFO "/proc/cpuinfo"
@@ -282,7 +288,7 @@ ec_code_prepare(ec_code_t *code, uint32_t count, uint32_t width,
builder = GF_MALLOC(sizeof(ec_code_builder_t) +
sizeof(ec_code_op_t) * count, ec_mt_ec_code_builder_t);
if (builder == NULL) {
- return NULL;
+ return EC_ERR(ENOMEM);
}
builder->address = 0;
@@ -323,15 +329,39 @@ ec_code_chunk_from_space(ec_code_space_t *space)
}
static void *
-ec_code_func_from_chunk(ec_code_chunk_t *chunk)
+ec_code_to_executable(ec_code_space_t *space, void *addr)
+{
+ return (void *)((uintptr_t)addr - (uintptr_t)space
+ + (uintptr_t)space->exec);
+}
+
+static void *
+ec_code_from_executable(ec_code_space_t *space, void *addr)
{
- return (void *)((uintptr_t)chunk + ec_code_chunk_size());
+ return (void *)((uintptr_t)addr - (uintptr_t)space->exec
+ + (uintptr_t)space);
+}
+
+static void *
+ec_code_func_from_chunk(ec_code_chunk_t *chunk, void **exec)
+{
+ void *addr;
+
+ addr = (void *)((uintptr_t)chunk + ec_code_chunk_size());
+
+ *exec = ec_code_to_executable(chunk->space, addr);
+
+ return addr;
}
static ec_code_chunk_t *
ec_code_chunk_from_func(ec_code_func_linear_t func)
{
- return (ec_code_chunk_t *)((uintptr_t)func - ec_code_chunk_size());
+ ec_code_chunk_t *chunk;
+
+ chunk = (ec_code_chunk_t *)((uintptr_t)func - ec_code_chunk_size());
+
+ return ec_code_from_executable(chunk->space, chunk);
}
static ec_code_chunk_t *
@@ -343,6 +373,7 @@ ec_code_chunk_split(ec_code_chunk_t *chunk, size_t size)
avail = chunk->size - size - ec_code_chunk_size();
if (avail > 0) {
extra = (ec_code_chunk_t *)((uintptr_t)chunk + chunk->size - avail);
+ extra->space = chunk->space;
extra->size = avail;
list_add(&extra->list, &chunk->list);
chunk->size = size;
@@ -361,18 +392,115 @@ ec_code_chunk_touch(ec_code_chunk_t *prev, ec_code_chunk_t *next)
return (end == (uintptr_t)next);
}
+static ec_code_space_t *
+ec_code_space_create(ec_code_t *code, size_t size)
+{
+ char path[] = GLUSTERFS_LIBEXECDIR "/ec-code-dynamic.XXXXXX";
+ ec_code_space_t *space;
+ void *exec;
+ int32_t fd, err;
+
+ /* We need to create memory areas to store the generated dynamic code.
+ * Obviously these areas need to be written to be able to create the
+ * code and they also need to be executable to execute it.
+ *
+ * However it's a bad practice to have a memory region that is both
+ * writable *and* executable. In fact, selinux forbids this and causes
+ * attempts to do so to fail (unless specifically configured).
+ *
+ * To solve the problem we'll use two distinct memory areas mapped to
+ * the same physical storage. One of the memory areas will have write
+ * permission, and the other will have execute permission. Both areas
+ * will have the same contents. The physical storage will be a regular
+ * file that will be mmapped to both areas.
+ */
+
+ /* We need to create a temporary file as the backend storage for the
+ * memory mapped areas. */
+ fd = mkstemp(path);
+ if (fd < 0) {
+ err = errno;
+ gf_msg(THIS->name, GF_LOG_ERROR, err, EC_MSG_DYN_CREATE_FAILED,
+ "Unable to create a temporary file for the ec dynamic "
+ "code");
+ space = EC_ERR(err);
+ goto done;
+ }
+ /* Once created we don't need to keep it in the file system. It will
+ * still exist until we close the last file descriptor or unmap the
+ * memory areas bound to the file. */
+ sys_unlink(path);
+
+ size = (size + EC_CODE_ALIGN - 1) & ~(EC_CODE_ALIGN - 1);
+ if (sys_ftruncate(fd, size) < 0) {
+ err = errno;
+ gf_msg(THIS->name, GF_LOG_ERROR, err, EC_MSG_DYN_CREATE_FAILED,
+ "Unable to resize the file for the ec dynamic code");
+ space = EC_ERR(err);
+ goto done_close;
+ }
+
+ /* This creates an executable memory area to be able to run the
+ * generated fragments of code. */
+ exec = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
+ if (exec == MAP_FAILED) {
+ err = errno;
+ gf_msg(THIS->name, GF_LOG_ERROR, err, EC_MSG_DYN_CREATE_FAILED,
+ "Unable to map the executable area for the ec dynamic "
+ "code");
+ space = EC_ERR(err);
+ goto done_close;
+ }
+ /* It's not important to check the return value of mlock(). If it fails
+ * everything will continue to work normally. */
+ mlock(exec, size);
+
+ /* This maps a read/write memory area to be able to create the dynamici
+ * code. */
+ space = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (space == MAP_FAILED) {
+ err = errno;
+ gf_msg(THIS->name, GF_LOG_ERROR, err, EC_MSG_DYN_CREATE_FAILED,
+ "Unable to map the writable area for the ec dynamic "
+ "code");
+ space = EC_ERR(err);
+
+ munmap(exec, size);
+
+ goto done_close;
+ }
+
+ space->exec = exec;
+ space->size = size;
+ space->code = code;
+ list_add_tail(&space->list, &code->spaces);
+ INIT_LIST_HEAD(&space->chunks);
+
+done_close:
+ /* If everything has succeeded, we already have the memory areas
+ * mapped. We don't need the file descriptor anymore because the
+ * backend storage will be there until the mmaped regions are
+ * unmapped. */
+ sys_close(fd);
+done:
+ return space;
+}
+
static void
-ec_code_chunk_merge(ec_code_chunk_t *chunk)
+ec_code_space_destroy(ec_code_space_t *space)
{
- ec_code_chunk_t *item;
+ list_del_init(&space->list);
- list_for_each_entry(item, &chunk->space->chunks, list) {
- if (ec_code_chunk_touch(item, chunk)) {
- item->size += chunk->size + ec_code_chunk_size();
- chunk = item;
+ munmap(space->exec, space->size);
+ munmap(space, space->size);
+}
- goto check;
- }
+static void
+ec_code_chunk_merge(ec_code_chunk_t *chunk)
+{
+ ec_code_chunk_t *item, *tmp;
+
+ list_for_each_entry_safe(item, tmp, &chunk->space->chunks, list) {
if ((uintptr_t)item > (uintptr_t)chunk) {
list_add_tail(&chunk->list, &item->list);
if (ec_code_chunk_touch(chunk, item)) {
@@ -382,15 +510,18 @@ ec_code_chunk_merge(ec_code_chunk_t *chunk)
goto check;
}
+ if (ec_code_chunk_touch(item, chunk)) {
+ item->size += chunk->size + ec_code_chunk_size();
+ list_del_init(&item->list);
+ chunk = item;
+ }
}
list_add_tail(&chunk->list, &chunk->space->chunks);
check:
- if (chunk->size == EC_CODE_SIZE - ec_code_space_size() -
- ec_code_chunk_size()) {
- list_del_init(&chunk->space->list);
-
- munmap(chunk->space, chunk->space->size);
+ if (chunk->size == chunk->space->size - ec_code_space_size() -
+ ec_code_chunk_size()) {
+ ec_code_space_destroy(chunk->space);
}
}
@@ -401,7 +532,10 @@ ec_code_space_alloc(ec_code_t *code, size_t size)
ec_code_chunk_t *chunk;
size_t map_size;
- size = (size + 15) & ~15;
+ /* To minimize fragmentation, we only allocate chunks of sizes multiples
+ * of EC_CODE_CHUNK_MIN_SIZE. */
+ size = ((size + ec_code_chunk_size() + EC_CODE_CHUNK_MIN_SIZE - 1) &
+ ~(EC_CODE_CHUNK_MIN_SIZE - 1)) - ec_code_chunk_size();
list_for_each_entry(space, &code->spaces, list) {
list_for_each_entry(chunk, &space->chunks, list) {
if (chunk->size >= size) {
@@ -410,26 +544,17 @@ ec_code_space_alloc(ec_code_t *code, size_t size)
}
}
- map_size = EC_CODE_SIZE;
+ map_size = EC_CODE_SIZE - ec_code_space_size() - ec_code_chunk_size();
if (map_size < size) {
map_size = size;
}
- space = mmap(NULL, map_size, PROT_EXEC | PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (space == NULL) {
- return NULL;
+ space = ec_code_space_create(code, map_size);
+ if (EC_IS_ERR(space)) {
+ return (ec_code_chunk_t *)space;
}
- /* It's not important to check the return value of mlock(). If it fails
- * everything will continue to work normally. */
- mlock(space, map_size);
-
- space->code = code;
- space->size = map_size;
- list_add_tail(&space->list, &code->spaces);
- INIT_LIST_HEAD(&space->chunks);
chunk = ec_code_chunk_from_space(space);
- chunk->size = EC_CODE_SIZE - ec_code_space_size() - ec_code_chunk_size();
+ chunk->size = map_size - ec_code_space_size() - ec_code_chunk_size();
list_add(&chunk->list, &space->chunks);
out:
@@ -465,7 +590,7 @@ ec_code_free(ec_code_chunk_t *chunk)
UNLOCK(lock);
}
-static gf_boolean_t
+static int32_t
ec_code_write(ec_code_builder_t *builder)
{
ec_code_gen_t *gen;
@@ -506,7 +631,7 @@ ec_code_write(ec_code_builder_t *builder)
}
gen->epilog(builder);
- return builder->error == 0;
+ return builder->error;
}
static void *
@@ -514,22 +639,24 @@ ec_code_compile(ec_code_builder_t *builder)
{
ec_code_chunk_t *chunk;
void *func;
+ int32_t err;
- if (!ec_code_write(builder)) {
- return NULL;
+ err = ec_code_write(builder);
+ if (err != 0) {
+ return EC_ERR(err);
}
chunk = ec_code_alloc(builder->code, builder->size);
- if (chunk == NULL) {
- return NULL;
+ if (EC_IS_ERR(chunk)) {
+ return chunk;
}
- func = ec_code_func_from_chunk(chunk);
- builder->data = (uint8_t *)func;
+ builder->data = ec_code_func_from_chunk(chunk, &func);
- if (!ec_code_write(builder)) {
+ err = ec_code_write(builder);
+ if (err != 0) {
ec_code_free(chunk);
- return NULL;
+ return EC_ERR(err);
}
GF_FREE(builder);
@@ -544,7 +671,7 @@ ec_code_create(ec_gf_t *gf, ec_code_gen_t *gen)
code = GF_MALLOC(sizeof(ec_code_t), ec_mt_ec_code_t);
if (code == NULL) {
- return NULL;
+ return EC_ERR(ENOMEM);
}
memset(code, 0, sizeof(ec_code_t));
INIT_LIST_HEAD(&code->spaces);
@@ -589,7 +716,7 @@ ec_code_value_next(uint32_t *values, uint32_t count, uint32_t *offset)
return next;
}
-void *
+static void *
ec_code_build(ec_code_t *code, uint32_t width, uint32_t *values,
uint32_t count, gf_boolean_t linear)
{
@@ -606,8 +733,8 @@ ec_code_build(ec_code_t *code, uint32_t width, uint32_t *values,
}
builder = ec_code_prepare(code, count, width, linear);
- if (builder == NULL) {
- return NULL;
+ if (EC_IS_ERR(builder)) {
+ return builder;
}
offset = -1;
@@ -659,6 +786,8 @@ void
ec_code_error(ec_code_builder_t *builder, int32_t error)
{
if (builder->error == 0) {
+ gf_msg(THIS->name, GF_LOG_ERROR, error, EC_MSG_DYN_CODEGEN_FAILED,
+ "Failed to generate dynamic code");
builder->error = error;
}
}
diff --git a/xlators/cluster/ec/src/ec-galois.c b/xlators/cluster/ec/src/ec-galois.c
index 7dbbac09713..8cb4dc2e4e3 100644
--- a/xlators/cluster/ec/src/ec-galois.c
+++ b/xlators/cluster/ec/src/ec-galois.c
@@ -15,6 +15,7 @@
#include "ec-mem-types.h"
#include "ec-gf8.h"
+#include "ec-helpers.h"
static ec_gf_t *
ec_gf_alloc(uint32_t bits, uint32_t mod)
@@ -48,7 +49,7 @@ failed_log:
failed_gf:
GF_FREE(gf);
failed:
- return NULL;
+ return EC_ERR(ENOMEM);
}
static void
@@ -79,7 +80,7 @@ ec_gf_prepare(uint32_t bits, uint32_t mod)
uint32_t i, j;
if (bits != 8) {
- return NULL;
+ return EC_ERR(EINVAL);
}
tbl = ec_gf8_mul;
@@ -88,8 +89,8 @@ ec_gf_prepare(uint32_t bits, uint32_t mod)
}
gf = ec_gf_alloc(bits, mod);
- if (gf == NULL) {
- return NULL;
+ if (EC_IS_ERR(gf)) {
+ return gf;
}
ec_gf_init_tables(gf);
diff --git a/xlators/cluster/ec/src/ec-helpers.h b/xlators/cluster/ec/src/ec-helpers.h
index dfea6fef537..0b355bd440e 100644
--- a/xlators/cluster/ec/src/ec-helpers.h
+++ b/xlators/cluster/ec/src/ec-helpers.h
@@ -13,6 +13,10 @@
#include "ec-types.h"
+#define EC_ERR(_x) ((void *)-(intptr_t)(_x))
+#define EC_IS_ERR(_x) (((uintptr_t)(_x) & ~0xfffULL) == ~0xfffULL)
+#define EC_GET_ERR(_x) ((int32_t)(intptr_t)(_x))
+
#define EC_ALIGN_CHECK(_ptr, _align) \
((((uintptr_t)(_ptr)) & ((_align) - 1)) == 0)
diff --git a/xlators/cluster/ec/src/ec-inode-read.c b/xlators/cluster/ec/src/ec-inode-read.c
index 6752b675273..775b2baa043 100644
--- a/xlators/cluster/ec/src/ec-inode-read.c
+++ b/xlators/cluster/ec/src/ec-inode-read.c
@@ -1186,7 +1186,11 @@ int32_t ec_readv_rebuild(ec_t * ec, ec_fop_data_t * fop, ec_cbk_data_t * cbk)
goto out;
}
- ec_method_decode(&ec->matrix, fsize, cbk->mask, values, blocks, ptr);
+ err = ec_method_decode(&ec->matrix, fsize, cbk->mask, values, blocks,
+ ptr);
+ if (err != 0) {
+ goto out;
+ }
vector[0].iov_base = ptr + fop->head;
vector[0].iov_len = size - fop->head;
diff --git a/xlators/cluster/ec/src/ec-messages.h b/xlators/cluster/ec/src/ec-messages.h
index dcdf50b9503..b034e9f203a 100644
--- a/xlators/cluster/ec/src/ec-messages.h
+++ b/xlators/cluster/ec/src/ec-messages.h
@@ -45,7 +45,7 @@
*/
#define GLFS_EC_COMP_BASE GLFS_MSGID_COMP_EC
-#define GLFS_NUM_MESSAGES 73
+#define GLFS_NUM_MESSAGES 75
#define GLFS_MSGID_END (GLFS_EC_COMP_BASE + GLFS_NUM_MESSAGES + 1)
/* Messaged with message IDs */
#define glfs_msg_start_x GLFS_EC_COMP_BASE, "Invalid: Start of messages"
@@ -569,6 +569,20 @@
*/
#define EC_MSG_MATRIX_FAILED (GLFS_EC_COMP_BASE + 73)
+/*!
+ * @messageid
+ * @diagnosis
+ * @recommendedaction
+ */
+#define EC_MSG_DYN_CREATE_FAILED (GLFS_EC_COMP_BASE + 74)
+
+/*!
+ * @messageid
+ * @diagnosis
+ * @recommendedaction
+ */
+#define EC_MSG_DYN_CODEGEN_FAILED (GLFS_EC_COMP_BASE + 75)
+
/*------------*/
#define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages"
diff --git a/xlators/cluster/ec/src/ec-method.c b/xlators/cluster/ec/src/ec-method.c
index d1b122fb6a4..41bf0406ecb 100644
--- a/xlators/cluster/ec/src/ec-method.c
+++ b/xlators/cluster/ec/src/ec-method.c
@@ -16,6 +16,7 @@
#include "ec-galois.h"
#include "ec-code.h"
#include "ec-method.h"
+#include "ec-helpers.h"
static void
ec_method_matrix_normal(ec_gf_t *gf, uint32_t *matrix, uint32_t columns,
@@ -69,11 +70,12 @@ ec_method_matrix_inverse(ec_gf_t *gf, uint32_t *matrix, uint32_t *values,
}
}
-static gf_boolean_t
+static int32_t
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;
@@ -92,8 +94,10 @@ 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 (matrix->row_data[i].func.interleaved == NULL) {
- return _gf_false;
+ 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 {
@@ -106,13 +110,15 @@ 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 (matrix->row_data[i].func.linear == NULL) {
- return _gf_false;
+ 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 _gf_true;
+ return err;
}
static void
@@ -212,6 +218,7 @@ 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);
@@ -233,16 +240,17 @@ ec_method_matrix_get(ec_matrix_list_t *list, uintptr_t mask, uint32_t *rows)
} else {
matrix = mem_get0(list->pool);
if (matrix == NULL) {
+ matrix = EC_ERR(ENOMEM);
goto out;
}
matrix->values = (uint32_t *)((uintptr_t)matrix + sizeof(ec_matrix_t) +
sizeof(ec_matrix_row_t) * list->columns);
}
- if (!ec_method_matrix_init(list, matrix, mask, rows, _gf_true)) {
+ err = ec_method_matrix_init(list, matrix, mask, rows, _gf_true);
+ if (err != 0) {
ec_method_matrix_unref(list, matrix);
-
- matrix = NULL;
+ matrix = EC_ERR(err);
goto out;
}
@@ -269,18 +277,20 @@ ec_method_matrix_put(ec_matrix_list_t *list, ec_matrix_t *matrix)
UNLOCK(&list->lock);
}
-static gf_boolean_t
+static int32_t
ec_method_setup(xlator_t *xl, ec_matrix_list_t *list, const char *gen)
{
ec_matrix_t *matrix;
uint32_t values[list->rows];
uint32_t i;
+ int32_t err;
matrix = GF_MALLOC(sizeof(ec_matrix_t) +
sizeof(ec_matrix_row_t) * list->rows +
sizeof(uint32_t) * list->columns * list->rows,
ec_mt_ec_matrix_t);
if (matrix == NULL) {
+ err = -ENOMEM;
goto failed;
}
memset(matrix, 0, sizeof(ec_matrix_t));
@@ -288,7 +298,9 @@ ec_method_setup(xlator_t *xl, ec_matrix_list_t *list, const char *gen)
sizeof(ec_matrix_row_t) * list->rows);
list->code = ec_code_create(list->gf, ec_code_detect(xl, gen));
- if (list->code == NULL) {
+ if (EC_IS_ERR(list->code)) {
+ err = EC_GET_ERR(list->code);
+ list->code = NULL;
goto failed_matrix;
}
list->width = list->code->width;
@@ -296,23 +308,24 @@ ec_method_setup(xlator_t *xl, ec_matrix_list_t *list, const char *gen)
for (i = 0; i < list->rows; i++) {
values[i] = i + 1;
}
- if (!ec_method_matrix_init(list, matrix, 0, values, _gf_false)) {
+ err = ec_method_matrix_init(list, matrix, 0, values, _gf_false);
+ if (err != 0) {
goto failed_code;
}
list->encode = matrix;
- return _gf_true;
+ return 0;
failed_code:
ec_code_destroy(list->code);
failed_matrix:
GF_FREE(matrix);
failed:
- return _gf_false;
+ return err;
}
-gf_boolean_t
+int32_t
ec_method_init(xlator_t *xl, ec_matrix_list_t *list, uint32_t columns,
uint32_t rows, uint32_t max, const char *gen)
{
@@ -321,32 +334,37 @@ ec_method_init(xlator_t *xl, ec_matrix_list_t *list, uint32_t columns,
list->max = max;
list->stripe = EC_METHOD_CHUNK_SIZE * list->columns;
INIT_LIST_HEAD(&list->lru);
+ int32_t err;
list->pool = mem_pool_new_fn(sizeof(ec_matrix_t) +
sizeof(ec_matrix_row_t) * columns +
sizeof(uint32_t) * columns * columns,
128, "ec_matrix_t");
if (list->pool == NULL) {
+ err = -ENOMEM;
goto failed;
}
list->objects = GF_MALLOC(sizeof(ec_matrix_t *) * max, ec_mt_ec_matrix_t);
if (list->objects == NULL) {
+ err = -ENOMEM;
goto failed_pool;
}
list->gf = ec_gf_prepare(EC_GF_BITS, EC_GF_MOD);
- if (list->gf == NULL) {
+ if (EC_IS_ERR(list->gf)) {
+ err = EC_GET_ERR(list->gf);
goto failed_objects;
}
- if (!ec_method_setup(xl, list, gen)) {
+ err = ec_method_setup(xl, list, gen);
+ if (err != 0) {
goto failed_gf;
}
LOCK_INIT(&list->lock);
- return _gf_true;
+ return 0;
failed_gf:
ec_gf_destroy(list->gf);
@@ -358,7 +376,8 @@ failed:
list->pool = NULL;
list->objects = NULL;
list->gf = NULL;
- return _gf_false;
+
+ return err;
}
void
@@ -389,12 +408,12 @@ ec_method_fini(ec_matrix_list_t *list)
mem_pool_destroy(list->pool);
}
-gf_boolean_t
+int32_t
ec_method_update(xlator_t *xl, ec_matrix_list_t *list, const char *gen)
{
/* TODO: Allow changing code generator */
- return _gf_true;
+ return 0;
}
void
@@ -415,7 +434,7 @@ ec_method_encode(ec_matrix_list_t *list, size_t size, void *in, void **out)
}
}
-gf_boolean_t
+int32_t
ec_method_decode(ec_matrix_list_t *list, size_t size, uintptr_t mask,
uint32_t *rows, void **in, void *out)
{
@@ -424,8 +443,8 @@ ec_method_decode(ec_matrix_list_t *list, size_t size, uintptr_t mask,
uint32_t i;
matrix = ec_method_matrix_get(list, mask, rows);
- if (matrix == NULL) {
- return _gf_false;
+ if (EC_IS_ERR(matrix)) {
+ return EC_GET_ERR(matrix);
}
for (pos = 0; pos < size; pos += EC_METHOD_CHUNK_SIZE) {
for (i = 0; i < matrix->rows; i++) {
@@ -438,5 +457,5 @@ ec_method_decode(ec_matrix_list_t *list, size_t size, uintptr_t mask,
ec_method_matrix_put(list, matrix);
- return _gf_true;
+ return 0;
}
diff --git a/xlators/cluster/ec/src/ec-method.h b/xlators/cluster/ec/src/ec-method.h
index 818b54de872..9ba5069ff0e 100644
--- a/xlators/cluster/ec/src/ec-method.h
+++ b/xlators/cluster/ec/src/ec-method.h
@@ -30,17 +30,20 @@
#define EC_METHOD_CHUNK_SIZE (EC_METHOD_WORD_SIZE * EC_GF_BITS)
-gf_boolean_t ec_method_init(xlator_t *xl, ec_matrix_list_t *list,
- uint32_t columns, uint32_t rows, uint32_t max,
- const char *gen);
+int32_t
+ec_method_init(xlator_t *xl, ec_matrix_list_t *list, uint32_t columns,
+ uint32_t rows, uint32_t max, const char *gen);
+
void ec_method_fini(ec_matrix_list_t *list);
-gf_boolean_t ec_method_update(xlator_t *xl, ec_matrix_list_t *list,
- const char *gen);
-
-void ec_method_encode(ec_matrix_list_t *list, size_t size, void *in,
- void **out);
-gf_boolean_t ec_method_decode(ec_matrix_list_t *list, size_t size,
- uintptr_t mask, uint32_t *rows, void **in,
- void *out);
+
+int32_t
+ec_method_update(xlator_t *xl, ec_matrix_list_t *list, const char *gen);
+
+void
+ec_method_encode(ec_matrix_list_t *list, size_t size, void *in, void **out);
+
+int32_t
+ec_method_decode(ec_matrix_list_t *list, size_t size, uintptr_t mask,
+ uint32_t *rows, void **in, void *out);
#endif /* __EC_METHOD_H__ */
diff --git a/xlators/cluster/ec/src/ec-types.h b/xlators/cluster/ec/src/ec-types.h
index de13b2562f1..751652c20b1 100644
--- a/xlators/cluster/ec/src/ec-types.h
+++ b/xlators/cluster/ec/src/ec-types.h
@@ -17,8 +17,6 @@
#define EC_GF_MAX_REGS 16
-#define EC_CODE_SIZE (1024 * 64)
-
enum _ec_read_policy;
typedef enum _ec_read_policy ec_read_policy_t;
@@ -453,6 +451,7 @@ struct _ec_code_space {
struct list_head list;
struct list_head chunks;
ec_code_t *code;
+ void *exec;
size_t size;
};
diff --git a/xlators/cluster/ec/src/ec.c b/xlators/cluster/ec/src/ec.c
index 7b16f8fd255..e467fea28b8 100644
--- a/xlators/cluster/ec/src/ec.c
+++ b/xlators/cluster/ec/src/ec.c
@@ -266,6 +266,7 @@ reconfigure (xlator_t *this, dict_t *options)
uint32_t heal_wait_qlen = 0;
uint32_t background_heals = 0;
int32_t ret = -1;
+ int32_t err;
GF_OPTION_RECONF ("cpu-extensions", extensions, options, str, failed);
@@ -295,7 +296,8 @@ reconfigure (xlator_t *this, dict_t *options)
ret = -1;
}
- if (!ec_method_update(this, &ec->matrix, extensions)) {
+ err = ec_method_update(this, &ec->matrix, extensions);
+ if (err != 0) {
ret = -1;
}
@@ -588,6 +590,7 @@ init (xlator_t *this)
ec_t *ec = NULL;
char *read_policy = NULL;
char *extensions = NULL;
+ int32_t err;
if (this->parents == NULL)
{
@@ -644,9 +647,10 @@ init (xlator_t *this)
GF_OPTION_INIT("cpu-extensions", extensions, str, failed);
- if (!ec_method_init(this, &ec->matrix, ec->fragments, ec->nodes,
- ec->nodes * 2, extensions)) {
- gf_msg (this->name, GF_LOG_ERROR, 0, EC_MSG_MATRIX_FAILED,
+ err = ec_method_init(this, &ec->matrix, ec->fragments, ec->nodes,
+ ec->nodes * 2, extensions);
+ if (err != 0) {
+ gf_msg (this->name, GF_LOG_ERROR, -err, EC_MSG_MATRIX_FAILED,
"Failed to initialize matrix management");
goto failed;