summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Hernandez <xhernandez@datalab.es>2014-09-18 16:50:47 +0200
committerVijay Bellur <vbellur@redhat.com>2014-09-23 22:46:58 -0700
commitc4440ab8c7417a3bcaadf1cb150476d5ff6a1325 (patch)
tree531d308bb79b29826a7dd10ca607c076dbef4063
parent6fffc4eaf408cb9b0b2891404ee54f4ab1dd5e2e (diff)
ec: Add config information in an xattr
To simplify backward compatibility of the ec xlator when some parameter or the implementation itself is changed, a new xattr is added to each file with the configuration needed to recover it. The new attribute is called 'trusted.ec.config', and it's a 64-bit value containing the following information: 8 bits: version of the config information (currently always 0) 8 bits: algorithm used to encode the file (currently always 0) 8 bits: size of the galois field (currently always 8) 8 bits: number of bricks 8 bits: redundancy 24 bits: chunk size (currently 512) This new xattr could allow, in a future version, to have different configurations per file. This is a backport of http://review.gluster.org/8770/ Change-Id: I8c12d40ff546cc201fc66caa367484be3d48aeb4 BUG: 1140862 Signed-off-by: Xavier Hernandez <xhernandez@datalab.es> Reviewed-on: http://review.gluster.org/8825 Reviewed-by: Dan Lambright <dlambrig@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r--xlators/cluster/ec/src/ec-common.c67
-rw-r--r--xlators/cluster/ec/src/ec-common.h4
-rw-r--r--xlators/cluster/ec/src/ec-data.h14
-rw-r--r--xlators/cluster/ec/src/ec-dir-write.c29
-rw-r--r--xlators/cluster/ec/src/ec-helpers.c64
-rw-r--r--xlators/cluster/ec/src/ec-helpers.h7
-rw-r--r--xlators/cluster/ec/src/ec.h1
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"