diff options
| author | Xavier Hernandez <xhernandez@datalab.es> | 2014-09-18 16:50:47 +0200 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2014-09-23 22:46:58 -0700 | 
| commit | c4440ab8c7417a3bcaadf1cb150476d5ff6a1325 (patch) | |
| tree | 531d308bb79b29826a7dd10ca607c076dbef4063 | |
| parent | 6fffc4eaf408cb9b0b2891404ee54f4ab1dd5e2e (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.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"  | 
