diff options
-rw-r--r-- | xlators/cluster/ec/src/ec-common.c | 67 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-common.h | 4 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-data.h | 14 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-dir-write.c | 29 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-helpers.c | 64 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-helpers.h | 7 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec.h | 1 |
7 files changed, 185 insertions, 1 deletions
diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c index 6d4855a9656..a7cf23d24bb 100644 --- a/xlators/cluster/ec/src/ec-common.c +++ b/xlators/cluster/ec/src/ec-common.c @@ -26,6 +26,7 @@ #include "ec-combine.h" #include "ec-common.h" #include "ec-fops.h" +#include "ec-method.h" #include "ec.h" int32_t ec_child_valid(ec_t * ec, ec_fop_data_t * fop, int32_t idx) @@ -992,12 +993,75 @@ int32_t ec_get_size_version_set(call_frame_t * frame, void * cookie, struct iatt * buf, dict_t * xdata, struct iatt * postparent) { + ec_t * ec; ec_fop_data_t * fop = cookie; ec_inode_t * ctx; ec_lock_t * lock; if (op_ret >= 0) { + if (buf->ia_type == IA_IFREG) + { + if (ec_dict_del_config(xdata, EC_XATTR_CONFIG, &fop->config) < 0) + { + gf_log(this->name, GF_LOG_ERROR, "Failed to get a valid " + "config"); + + ec_fop_set_error(fop, EIO); + + return 0; + } + ec = this->private; + if ((fop->config.version != EC_CONFIG_VERSION) || + (fop->config.algorithm != EC_CONFIG_ALGORITHM) || + (fop->config.gf_word_size != EC_GF_BITS) || + (fop->config.bricks != ec->nodes) || + (fop->config.redundancy != ec->redundancy) || + (fop->config.chunk_size != EC_METHOD_CHUNK_SIZE)) + { + uint32_t data_bricks; + + // This combination of version/algorithm requires the following + // values. Incorrect values for these fields are a sign of + // corruption: + // + // redundancy > 0 + // redundancy * 2 < bricks + // gf_word_size must be a power of 2 + // chunk_size (in bits) must be a multiple of gf_word_size * + // (bricks - redundancy) + + data_bricks = fop->config.bricks - fop->config.redundancy; + if ((fop->config.redundancy < 1) || + (fop->config.redundancy * 2 >= fop->config.bricks) || + !ec_is_power_of_2(fop->config.gf_word_size) || + ((fop->config.chunk_size * 8) % (fop->config.gf_word_size * + data_bricks) != 0)) + { + gf_log(this->name, GF_LOG_ERROR, "Invalid or corrupted " + "config (V=%u, A=%u, " + "W=%u, N=%u, R=%u, S=%u)", + fop->config.version, fop->config.algorithm, + fop->config.gf_word_size, fop->config.bricks, + fop->config.redundancy, fop->config.chunk_size); + } + else + { + gf_log(this->name, GF_LOG_ERROR, "Unsupported config " + "(V=%u, A=%u, W=%u, " + "N=%u, R=%u, S=%u)", + fop->config.version, fop->config.algorithm, + fop->config.gf_word_size, fop->config.bricks, + fop->config.redundancy, fop->config.chunk_size); + } + + ec_fop_set_error(fop, EIO); + + return 0; + } + } + + LOCK(&inode->lock); ctx = __ec_inode_get(inode, this); @@ -1065,7 +1129,8 @@ void ec_get_size_version(ec_fop_data_t * fop) goto out; } if ((dict_set_uint64(xdata, EC_XATTR_VERSION, 0) != 0) || - (dict_set_uint64(xdata, EC_XATTR_SIZE, 0) != 0)) + (dict_set_uint64(xdata, EC_XATTR_SIZE, 0) != 0) || + (dict_set_uint64(xdata, EC_XATTR_CONFIG, 0) != 0)) { goto out; } diff --git a/xlators/cluster/ec/src/ec-common.h b/xlators/cluster/ec/src/ec-common.h index 4fc89fdde33..79263e2d884 100644 --- a/xlators/cluster/ec/src/ec-common.h +++ b/xlators/cluster/ec/src/ec-common.h @@ -25,6 +25,10 @@ #include "ec-data.h" +#define EC_CONFIG_VERSION 0 + +#define EC_CONFIG_ALGORITHM 0 + #define EC_FLAG_UPDATE_LOC_PARENT 0x0001 #define EC_FLAG_UPDATE_LOC_INODE 0x0002 #define EC_FLAG_UPDATE_FD 0x0004 diff --git a/xlators/cluster/ec/src/ec-data.h b/xlators/cluster/ec/src/ec-data.h index 71f047a9aba..49090933ade 100644 --- a/xlators/cluster/ec/src/ec-data.h +++ b/xlators/cluster/ec/src/ec-data.h @@ -25,6 +25,9 @@ #include "ec.h" +struct _ec_config; +typedef struct _ec_config ec_config_t; + struct _ec_fd; typedef struct _ec_fd ec_fd_t; @@ -53,6 +56,16 @@ typedef void (* ec_wind_f)(ec_t *, ec_fop_data_t *, int32_t); typedef int32_t (* ec_handler_f)(ec_fop_data_t *, int32_t); typedef void (* ec_resume_f)(ec_fop_data_t *, int32_t); +struct _ec_config +{ + uint32_t version; + uint8_t algorithm; + uint8_t gf_word_size; + uint8_t bricks; + uint8_t redundancy; + uint32_t chunk_size; +}; + struct _ec_fd { uintptr_t bad; @@ -184,6 +197,7 @@ struct _ec_fop_data uint64_t pre_size; uint64_t post_size; gf_lock_t lock; + ec_config_t config; uint32_t flags; uint32_t first; diff --git a/xlators/cluster/ec/src/ec-dir-write.c b/xlators/cluster/ec/src/ec-dir-write.c index a28b7ad1937..92012855087 100644 --- a/xlators/cluster/ec/src/ec-dir-write.c +++ b/xlators/cluster/ec/src/ec-dir-write.c @@ -149,6 +149,7 @@ void ec_wind_create(ec_t * ec, ec_fop_data_t * fop, int32_t idx) int32_t ec_manager_create(ec_fop_data_t * fop, int32_t state) { + ec_t * ec; ec_cbk_data_t * cbk; ec_fd_t * ctx; @@ -175,6 +176,34 @@ int32_t ec_manager_create(ec_fop_data_t * fop, int32_t state) UNLOCK(&fop->fd->lock); + if (fop->xdata == NULL) + { + fop->xdata = dict_new(); + if (fop->xdata == NULL) + { + fop->error = EIO; + + return EC_STATE_REPORT; + } + } + + ec = fop->xl->private; + + fop->config.version = EC_CONFIG_VERSION; + fop->config.algorithm = EC_CONFIG_ALGORITHM; + fop->config.gf_word_size = EC_GF_BITS; + fop->config.bricks = ec->nodes; + fop->config.redundancy = ec->redundancy; + fop->config.chunk_size = EC_METHOD_CHUNK_SIZE; + + if (ec_dict_set_config(fop->xdata, EC_XATTR_CONFIG, + &fop->config) < 0) + { + fop->error = EIO; + + return EC_STATE_REPORT; + } + fop->int32 &= ~O_ACCMODE; fop->int32 |= O_RDWR; diff --git a/xlators/cluster/ec/src/ec-helpers.c b/xlators/cluster/ec/src/ec-helpers.c index 181a6f7b41a..534d694cc52 100644 --- a/xlators/cluster/ec/src/ec-helpers.c +++ b/xlators/cluster/ec/src/ec-helpers.c @@ -246,6 +246,70 @@ int32_t ec_dict_del_number(dict_t * dict, char * key, uint64_t * value) return 0; } +int32_t ec_dict_set_config(dict_t * dict, char * key, ec_config_t * config) +{ + uint64_t * ptr, data; + + if (config->version > EC_CONFIG_VERSION) + { + gf_log("ec", GF_LOG_ERROR, "Trying to store an unsupported config " + "version (%u)", config->version); + + return -1; + } + + ptr = GF_MALLOC(sizeof(uint64_t), gf_common_mt_char); + if (ptr == NULL) + { + return -1; + } + + data = ((uint64_t)config->version) << 56; + data |= ((uint64_t)config->algorithm) << 48; + data |= ((uint64_t)config->gf_word_size) << 40; + data |= ((uint64_t)config->bricks) << 32; + data |= ((uint64_t)config->redundancy) << 24; + data |= config->chunk_size; + + *ptr = hton64(data); + + return dict_set_bin(dict, key, ptr, sizeof(uint64_t)); +} + +int32_t ec_dict_del_config(dict_t * dict, char * key, ec_config_t * config) +{ + void * ptr; + uint64_t data; + int32_t len; + + if ((dict == NULL) || (dict_get_ptr_and_len(dict, key, &ptr, &len) != 0) || + (len != sizeof(uint64_t))) + { + return -1; + } + + data = ntoh64(*(uint64_t *)ptr); + + config->version = (data >> 56) & 0xff; + if (config->version > EC_CONFIG_VERSION) + { + gf_log("ec", GF_LOG_ERROR, "Found an unsupported config version (%u)", + config->version); + + return -1; + } + + config->algorithm = (data >> 48) & 0xff; + config->gf_word_size = (data >> 40) & 0xff; + config->bricks = (data >> 32) & 0xff; + config->redundancy = (data >> 24) & 0xff; + config->chunk_size = data & 0xffffff; + + dict_del(dict, key); + + return 0; +} + int32_t ec_loc_gfid_check(xlator_t * xl, uuid_t dst, uuid_t src) { if (uuid_is_null(src)) diff --git a/xlators/cluster/ec/src/ec-helpers.h b/xlators/cluster/ec/src/ec-helpers.h index 3010ea856de..044e6239e8b 100644 --- a/xlators/cluster/ec/src/ec-helpers.h +++ b/xlators/cluster/ec/src/ec-helpers.h @@ -36,6 +36,8 @@ size_t ec_iov_copy_to(void * dst, struct iovec * vector, int32_t count, int32_t ec_dict_set_number(dict_t * dict, char * key, uint64_t value); int32_t ec_dict_del_number(dict_t * dict, char * key, uint64_t * value); +int32_t ec_dict_set_config(dict_t * dict, char * key, ec_config_t * config); +int32_t ec_dict_del_config(dict_t * dict, char * key, ec_config_t * config); int32_t ec_loc_parent(xlator_t * xl, loc_t * loc, loc_t * parent, char ** name); @@ -56,4 +58,9 @@ ec_fd_t * ec_fd_get(fd_t * fd, xlator_t * xl); uint32_t ec_adjust_offset(ec_t * ec, off_t * offset, int32_t scale); uint64_t ec_adjust_size(ec_t * ec, uint64_t size, int32_t scale); +static inline int32_t ec_is_power_of_2(uint32_t value) +{ + return (value != 0) && ((value & (value - 1)) == 0); +} + #endif /* __EC_HELPERS_H__ */ diff --git a/xlators/cluster/ec/src/ec.h b/xlators/cluster/ec/src/ec.h index 0cc8fdb4403..3b29a2e7a93 100644 --- a/xlators/cluster/ec/src/ec.h +++ b/xlators/cluster/ec/src/ec.h @@ -24,6 +24,7 @@ #include "xlator.h" #include "timer.h" +#define EC_XATTR_CONFIG "trusted.ec.config" #define EC_XATTR_SIZE "trusted.ec.size" #define EC_XATTR_VERSION "trusted.ec.version" |