cluster/ec: Don't handle EC_XATTR_DIRTY in response
Problem: ec_update_size_version expects all the keys it did xattrop with to come in response so that it can set the values again in ec_update_size_version_done. But EC_XATTR_DIRTY is not combined so the value won't be present in the response. So ctx->post/pre_dirty are not updated in ec_update_size_version_done. So these values are still non-zero. When ec_unlock_now is called as part of flush's unlock phase it again tries to perform same xattrop for EC_XATTR_DIRTY. But ec_update_size_version is not expected to be called in unlock phase of flush because ec_flush_size_version should have reset everything to zero and unlock is never invoked from ec_update_size_version_done for flush/fsync/fsyncdir. This leads to stale lock which leads to hang. Fix: EC_XATTR_DIRTY is removed in ex_xattrop_cbk and is never combined with other answers. So remove handling of this in the response. Change-Id: If0ea3efec3235a6e312465d8838585fbe752c7ea BUG: 1227654 Signed-off-by: Pranith Kumar K <pkarampu@redhat.com> Reviewed-on: http://review.gluster.org/11078 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
This commit is contained in:
parent
8f12fae9cb
commit
3373379303
@ -884,14 +884,6 @@ ec_prepare_update_cbk (call_frame_t *frame, void *cookie,
|
||||
|
||||
ctx->have_version = _gf_true;
|
||||
|
||||
if (ec_dict_del_array(dict, EC_XATTR_DIRTY, ctx->pre_dirty,
|
||||
EC_VERSION_SIZE) == 0) {
|
||||
ctx->post_dirty[0] += ctx->pre_dirty[0];
|
||||
ctx->post_dirty[1] += ctx->pre_dirty[1];
|
||||
|
||||
ctx->have_dirty = _gf_true;
|
||||
}
|
||||
|
||||
if (lock->loc.inode->ia_type == IA_IFREG) {
|
||||
if (ec_dict_del_number(dict, EC_XATTR_SIZE, &ctx->pre_size) != 0) {
|
||||
gf_log(this->name, GF_LOG_ERROR, "Unable to get size xattr");
|
||||
@ -1107,14 +1099,12 @@ void ec_clear_inode_info(ec_fop_data_t *fop, inode_t *inode)
|
||||
ctx->have_config = _gf_false;
|
||||
ctx->have_version = _gf_false;
|
||||
ctx->have_size = _gf_false;
|
||||
ctx->have_dirty = _gf_false;
|
||||
|
||||
memset(&ctx->config, 0, sizeof(ctx->config));
|
||||
memset(ctx->pre_version, 0, sizeof(ctx->pre_version));
|
||||
memset(ctx->post_version, 0, sizeof(ctx->post_version));
|
||||
ctx->pre_size = ctx->post_size = 0;
|
||||
memset(ctx->pre_dirty, 0, sizeof(ctx->pre_dirty));
|
||||
memset(ctx->post_dirty, 0, sizeof(ctx->post_dirty));
|
||||
memset(ctx->dirty, 0, sizeof(ctx->dirty));
|
||||
|
||||
unlock:
|
||||
UNLOCK(&inode->lock);
|
||||
@ -1472,13 +1462,6 @@ int32_t ec_update_size_version_done(call_frame_t * frame, void * cookie,
|
||||
|
||||
ctx->have_size = _gf_true;
|
||||
}
|
||||
if (ec_dict_del_array(xattr, EC_XATTR_DIRTY, ctx->post_dirty,
|
||||
EC_VERSION_SIZE) == 0) {
|
||||
ctx->pre_dirty[0] = ctx->post_dirty[0];
|
||||
ctx->pre_dirty[1] = ctx->post_dirty[1];
|
||||
|
||||
ctx->have_dirty = _gf_true;
|
||||
}
|
||||
if ((ec_dict_del_config(xdata, EC_XATTR_CONFIG, &ctx->config) == 0) &&
|
||||
ec_config_check(fop->parent, &ctx->config)) {
|
||||
ctx->have_config = _gf_true;
|
||||
@ -1541,7 +1524,7 @@ ec_update_size_version(ec_lock_link_t *link, uint64_t *version,
|
||||
|
||||
/* If we don't have dirty information or it has been modified, we update
|
||||
* it. */
|
||||
if (!ctx->have_dirty || (dirty[0] != 0) || (dirty[1] != 0)) {
|
||||
if ((dirty[0] != 0) || (dirty[1] != 0)) {
|
||||
if (ec_dict_set_array(dict, EC_XATTR_DIRTY, dirty,
|
||||
EC_VERSION_SIZE) != 0) {
|
||||
goto out;
|
||||
@ -1606,9 +1589,10 @@ ec_update_info(ec_lock_link_t *link)
|
||||
|
||||
size = ctx->post_size - ctx->pre_size;
|
||||
|
||||
/* pre_dirty[*] will be 0 if have_dirty is false */
|
||||
dirty[0] = ctx->post_dirty[0] - ctx->pre_dirty[0];
|
||||
dirty[1] = ctx->post_dirty[1] - ctx->pre_dirty[1];
|
||||
dirty[0] = ctx->dirty[0];
|
||||
dirty[1] = ctx->dirty[1];
|
||||
/*Dirty is not combined so just reset it right here*/
|
||||
memset(ctx->dirty, 0, sizeof(ctx->dirty));
|
||||
|
||||
if ((version[0] != 0) || (version[1] != 0) ||
|
||||
(dirty[0] != 0) || (dirty[1] != 0)) {
|
||||
@ -1817,13 +1801,13 @@ void ec_lock_reuse(ec_fop_data_t *fop)
|
||||
if (link->update[0]) {
|
||||
ctx->post_version[0]++;
|
||||
if (ec->node_mask & ~fop->mask) {
|
||||
ctx->post_dirty[0]++;
|
||||
ctx->dirty[0]++;
|
||||
}
|
||||
}
|
||||
if (link->update[1]) {
|
||||
ctx->post_version[1]++;
|
||||
if (ec->node_mask & ~fop->mask) {
|
||||
ctx->post_dirty[1]++;
|
||||
ctx->dirty[1]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,14 +72,12 @@ struct _ec_inode
|
||||
gf_boolean_t have_config;
|
||||
gf_boolean_t have_version;
|
||||
gf_boolean_t have_size;
|
||||
gf_boolean_t have_dirty;
|
||||
ec_config_t config;
|
||||
uint64_t pre_version[2];
|
||||
uint64_t post_version[2];
|
||||
uint64_t pre_size;
|
||||
uint64_t post_size;
|
||||
uint64_t pre_dirty[2];
|
||||
uint64_t post_dirty[2];
|
||||
uint64_t dirty[2];
|
||||
struct list_head heal;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user