diff options
author | Brian Foster <bfoster@redhat.com> | 2012-11-01 09:33:53 -0400 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2012-11-29 09:34:14 -0800 |
commit | b90b2c17b6b678e5aa1440a62b7588f8b7c52947 (patch) | |
tree | d8cd13c379bb819a189a41baff2d2935ac0136e1 /xlators/cluster/afr/src/afr-self-heal-data.c | |
parent | 0314f16ec59d8c22597c8c14b53a473b736b8b1f (diff) |
afr: send unique dict_t instances to replicas in self-heal fxattrop
afr_sh_data_fxattrop() currently allocates and sends a single xattr
dict_t instance to each replica. The callback codepath references
the returned object in the self-heal in-memory state for the
particular replica. If storage/posix is in the same address-space
(i.e., running a single glusterfs client with a fuse->afr->posix
graph), the same object is modified and returned for each child,
causing corrupted in-memory state and afr xattrs.
Allocate and send independent xattr dict_t's for each replica. This
allows self-heal to work correctly in a single address-space
graph.
BUG: 868478
Change-Id: I42832e85b5d1abb6098c28944c717e129300109e
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-on: http://review.gluster.org/4149
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'xlators/cluster/afr/src/afr-self-heal-data.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-data.c | 70 |
1 files changed, 42 insertions, 28 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-data.c b/xlators/cluster/afr/src/afr-self-heal-data.c index 42bc0afc18d..5e1e6fe9f6d 100644 --- a/xlators/cluster/afr/src/afr-self-heal-data.c +++ b/xlators/cluster/afr/src/afr-self-heal-data.c @@ -987,11 +987,12 @@ afr_sh_data_fxattrop (call_frame_t *frame, xlator_t *this) afr_self_heal_t *sh = NULL; afr_local_t *local = NULL; afr_private_t *priv = NULL; - dict_t *xattr_req = NULL; + dict_t **xattr_req; int32_t *zero_pending = NULL; int call_count = 0; int i = 0; int ret = 0; + int j; priv = this->private; local = frame->local; @@ -1002,30 +1003,39 @@ afr_sh_data_fxattrop (call_frame_t *frame, xlator_t *this) local->call_count = call_count; - xattr_req = dict_new(); - if (!xattr_req) { - ret = -1; - goto out; - } - - for (i = 0; i < priv->child_count; i++) { - zero_pending = GF_CALLOC (3, sizeof (*zero_pending), - gf_afr_mt_int32_t); - if (!zero_pending) { - ret = -1; - goto out; - } - ret = dict_set_dynptr (xattr_req, priv->pending_key[i], - zero_pending, - 3 * sizeof (*zero_pending)); - if (ret < 0) { - gf_log (this->name, GF_LOG_WARNING, - "Unable to set dict value"); - goto out; - } else { - zero_pending = NULL; - } - } + xattr_req = GF_CALLOC(priv->child_count, sizeof(struct dict_t *), + gf_afr_mt_dict_t); + if (!xattr_req) + goto out; + + for (i = 0; i < priv->child_count; i++) { + xattr_req[i] = dict_new(); + if (!xattr_req[i]) { + ret = -1; + goto out; + } + } + + for (i = 0; i < priv->child_count; i++) { + for (j = 0; j < priv->child_count; j++) { + zero_pending = GF_CALLOC (3, sizeof (*zero_pending), + gf_afr_mt_int32_t); + if (!zero_pending) { + ret = -1; + goto out; + } + ret = dict_set_dynptr (xattr_req[i], priv->pending_key[j], + zero_pending, + 3 * sizeof (*zero_pending)); + if (ret < 0) { + gf_log (this->name, GF_LOG_WARNING, + "Unable to set dict value"); + goto out; + } else { + zero_pending = NULL; + } + } + } afr_reset_xattr (sh->xattr, priv->child_count); afr_reset_children (sh->success_children, priv->child_count); @@ -1039,7 +1049,7 @@ afr_sh_data_fxattrop (call_frame_t *frame, xlator_t *this) priv->children[i], priv->children[i]->fops->fxattrop, sh->healing_fd, GF_XATTROP_ADD_ARRAY, - xattr_req, NULL); + xattr_req[i], NULL); if (!--call_count) break; @@ -1047,8 +1057,12 @@ afr_sh_data_fxattrop (call_frame_t *frame, xlator_t *this) } out: - if (xattr_req) - dict_unref (xattr_req); + if (xattr_req) { + for (i = 0; i < priv->child_count; i++) + if (xattr_req[i]) + dict_unref(xattr_req[i]); + GF_FREE(xattr_req); + } if (ret) { GF_FREE (zero_pending); |