From 17cb0e4782f47339dd1e4edc2e166ff2422da750 Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Thu, 4 Jun 2015 09:52:51 +0530 Subject: [PATCH 14/18] cluster/ec: EC_XATTR_DIRTY doesn't come in response Backport of http://review.gluster.com/11084 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. BUG: 1227649 Change-Id: I657efca6e706e7acb541f98f526943f67562da9f Signed-off-by: Pranith Kumar K Reviewed-on: https://code.engineering.redhat.com/gerrit/49909 --- xlators/cluster/ec/src/ec-common.c | 32 ++++++++------------------------ xlators/cluster/ec/src/ec-data.h | 4 +--- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c index ba81fc7..062754b 100644 --- a/xlators/cluster/ec/src/ec-common.c +++ b/xlators/cluster/ec/src/ec-common.c @@ -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]++; } } } diff --git a/xlators/cluster/ec/src/ec-data.h b/xlators/cluster/ec/src/ec-data.h index 8204cf0..8f6d5de 100644 --- a/xlators/cluster/ec/src/ec-data.h +++ b/xlators/cluster/ec/src/ec-data.h @@ -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; }; -- 1.9.3