diff options
Diffstat (limited to 'xlators/cluster/ec/src/ec-common.c')
-rw-r--r-- | xlators/cluster/ec/src/ec-common.c | 283 |
1 files changed, 209 insertions, 74 deletions
diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c index fcae083aa84..92f7657cd75 100644 --- a/xlators/cluster/ec/src/ec-common.c +++ b/xlators/cluster/ec/src/ec-common.c @@ -936,78 +936,77 @@ void ec_lock(ec_fop_data_t * fop) } } +gf_boolean_t +ec_config_check (ec_fop_data_t *fop, dict_t *xdata) +{ + ec_t *ec; + + if (ec_dict_del_config(xdata, EC_XATTR_CONFIG, &fop->config) < 0) { + gf_log(fop->xl->name, GF_LOG_ERROR, "Failed to get a valid " + "config"); + + ec_fop_set_error(fop, EIO); + + return _gf_false; + } + + ec = fop->xl->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(fop->xl->name, GF_LOG_ERROR, "Invalid or corrupted config"); + } else { + gf_log(fop->xl->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 _gf_false; + } + + return _gf_true; +} + int32_t ec_get_size_version_set(call_frame_t * frame, void * cookie, xlator_t * this, int32_t op_ret, int32_t op_errno, inode_t * inode, 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 = NULL; 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; - } + if ((buf->ia_type == IA_IFREG) && !ec_config_check(fop, xdata)) { + return 0; } LOCK(&inode->lock); @@ -1053,6 +1052,58 @@ int32_t ec_get_size_version_set(call_frame_t * frame, void * cookie, return 0; } +int32_t ec_prepare_update_cbk(call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, int32_t op_errno, + dict_t *dict, dict_t *xdata) +{ + ec_fop_data_t *fop = cookie, *parent; + ec_lock_t *lock = NULL; + + if (op_ret >= 0) { + parent = fop->parent; + while ((parent != NULL) && (parent->locks[0].lock == NULL)) { + parent = parent->parent; + } + if (parent == NULL) { + return 0; + } + + lock = parent->locks[0].lock; + lock->is_dirty = _gf_true; + + if (!ec_config_check(fop, dict)) { + return 0; + } + + LOCK(&lock->loc.inode->lock); + + if ((ec_dict_del_number(dict, EC_XATTR_VERSION, &lock->version) != 0) || + (ec_dict_del_number(dict, EC_XATTR_SIZE, &lock->size) != 0)) { + UNLOCK(&lock->loc.inode->lock); + + ec_fop_set_error(fop, EIO); + + return 0; + } + + lock->have_size = 1; + + UNLOCK(&lock->loc.inode->lock); + + fop->parent->mask &= fop->good; + + fop->parent->pre_size = fop->parent->post_size = lock->size; + fop->parent->have_size = 1; + } else { + gf_log(this->name, GF_LOG_WARNING, + "Failed to get size and version (error %d: %s)", op_errno, + strerror (op_errno)); + ec_fop_set_error(fop, op_errno); + } + + return 0; +} + void ec_get_size_version(ec_fop_data_t * fop) { loc_t loc; @@ -1085,7 +1136,8 @@ void ec_get_size_version(ec_fop_data_t * fop) } 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_CONFIG, 0) != 0)) + (dict_set_uint64(xdata, EC_XATTR_CONFIG, 0) != 0) || + (dict_set_uint64(xdata, EC_XATTR_DIRTY, 0) != 0)) { goto out; } @@ -1141,7 +1193,84 @@ out: dict_unref(xdata); } - ec_fop_set_error(fop, error); + if (error != 0) { + ec_fop_set_error(fop, error); + } +} + +void ec_prepare_update(ec_fop_data_t *fop) +{ + loc_t loc; + dict_t *xdata; + ec_fop_data_t *tmp; + ec_lock_t *lock; + uid_t uid; + gid_t gid; + int32_t error = ENOMEM; + + tmp = fop; + while ((tmp != NULL) && (tmp->locks[0].lock == NULL)) { + tmp = tmp->parent; + } + if ((tmp != NULL) && tmp->locks[0].lock->is_dirty) { + lock = tmp->locks[0].lock; + + fop->pre_size = fop->post_size = lock->size; + fop->have_size = 1; + + return; + } + + memset(&loc, 0, sizeof(loc)); + + xdata = dict_new(); + if (xdata == NULL) { + goto out; + } + if ((ec_dict_set_number(xdata, EC_XATTR_VERSION, 0) != 0) || + (ec_dict_set_number(xdata, EC_XATTR_SIZE, 0) != 0) || + (ec_dict_set_number(xdata, EC_XATTR_CONFIG, 0) != 0) || + (ec_dict_set_number(xdata, EC_XATTR_DIRTY, 1) != 0)) { + goto out; + } + + uid = fop->frame->root->uid; + gid = fop->frame->root->gid; + + fop->frame->root->uid = 0; + fop->frame->root->gid = 0; + + error = EIO; + + if (!fop->use_fd) { + if (ec_loc_from_loc(fop->xl, &loc, &fop->loc[0]) != 0) { + goto out; + } + + ec_xattrop(fop->frame, fop->xl, fop->mask, fop->minimum, + ec_prepare_update_cbk, NULL, &loc, GF_XATTROP_ADD_ARRAY64, + xdata, NULL); + } else { + ec_fxattrop(fop->frame, fop->xl, fop->mask, fop->minimum, + ec_prepare_update_cbk, NULL, fop->fd, + GF_XATTROP_ADD_ARRAY64, xdata, NULL); + } + + fop->frame->root->uid = uid; + fop->frame->root->gid = gid; + + error = 0; + +out: + loc_wipe(&loc); + + if (xdata != NULL) { + dict_unref(xdata); + } + + if (error != 0) { + ec_fop_set_error(fop, error); + } } int32_t ec_unlocked(call_frame_t *frame, void *cookie, xlator_t *this, @@ -1221,7 +1350,7 @@ int32_t ec_update_size_version_done(call_frame_t * frame, void * cookie, } void ec_update_size_version(ec_fop_data_t *fop, loc_t *loc, uint64_t version, - uint64_t size, ec_lock_t *lock) + uint64_t size, gf_boolean_t dirty, ec_lock_t *lock) { dict_t * dict; uid_t uid; @@ -1234,7 +1363,8 @@ void ec_update_size_version(ec_fop_data_t *fop, loc_t *loc, uint64_t version, return; } - ec_trace("UPDATE", fop, "version=%ld, size=%ld", version, size); + ec_trace("UPDATE", fop, "version=%ld, size=%ld, dirty=%u", version, size, + dirty); dict = dict_new(); if (dict == NULL) @@ -1242,14 +1372,18 @@ void ec_update_size_version(ec_fop_data_t *fop, loc_t *loc, uint64_t version, goto out; } - if (ec_dict_set_number(dict, EC_XATTR_VERSION, version) != 0) - { - goto out; + if (version != 0) { + if (ec_dict_set_number(dict, EC_XATTR_VERSION, version) != 0) { + goto out; + } } - if (size != 0) - { - if (ec_dict_set_number(dict, EC_XATTR_SIZE, size) != 0) - { + if (size != 0) { + if (ec_dict_set_number(dict, EC_XATTR_SIZE, size) != 0) { + goto out; + } + } + if (dirty) { + if (ec_dict_set_number(dict, EC_XATTR_DIRTY, -1) != 0) { goto out; } } @@ -1286,9 +1420,9 @@ void ec_unlock_now(ec_fop_data_t *fop, ec_lock_t *lock) { ec_trace("UNLOCK_NOW", fop, "lock=%p", lock); - if (lock->version_delta != 0) { + if ((lock->version_delta != 0) || lock->is_dirty) { ec_update_size_version(fop, &lock->loc, lock->version_delta, - lock->size_delta, lock); + lock->size_delta, lock->is_dirty, lock); } else { ec_unlock_lock(fop, lock); } @@ -1413,7 +1547,8 @@ void ec_flush_size_version(ec_fop_data_t * fop) if (version > 0) { - ec_update_size_version(fop, &lock->loc, version, delta, NULL); + ec_update_size_version(fop, &lock->loc, version, delta, _gf_false, + NULL); } } |