diff options
Diffstat (limited to 'xlators/cluster/afr/src/afr-common.c')
-rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 198 |
1 files changed, 174 insertions, 24 deletions
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c index 8fbca0b6f42..46f726da734 100644 --- a/xlators/cluster/afr/src/afr-common.c +++ b/xlators/cluster/afr/src/afr-common.c @@ -413,6 +413,142 @@ out: return ret; } +int +afr_spb_choice_timeout_cancel (xlator_t *this, inode_t *inode) +{ + afr_inode_ctx_t *ctx = NULL; + int ret = -1; + + if (!inode) + return ret; + + LOCK(&inode->lock); + { + __afr_inode_ctx_get (this, inode, &ctx); + if (!ctx) { + gf_log (this->name, GF_LOG_WARNING, "Failed to cancel" + " split-brain choice timer."); + goto out; + } + ctx->spb_choice = -1; + if (ctx->timer) { + gf_timer_call_cancel (this->ctx, ctx->timer); + ctx->timer = NULL; + } + ret = 0; + } +out: + UNLOCK(&inode->lock); + return ret; +} + +void +afr_set_split_brain_choice_cbk (void *data) +{ + inode_t *inode = data; + xlator_t *this = THIS; + + afr_spb_choice_timeout_cancel (this, inode); + inode_unref (inode); + return; +} + + +int +afr_set_split_brain_choice (int ret, call_frame_t *frame, void *opaque) +{ + int op_errno = ENOMEM; + afr_private_t *priv = NULL; + afr_inode_ctx_t *ctx = NULL; + inode_t *inode = NULL; + loc_t *loc = NULL; + xlator_t *this = NULL; + afr_spbc_timeout_t *data = opaque; + struct timespec delta = {0, }; + + if (ret) + goto out; + + frame = data->frame; + loc = data->loc; + this = frame->this; + priv = this->private; + + delta.tv_sec = priv->spb_choice_timeout; + delta.tv_nsec = 0; + + inode = loc->inode; + if (!inode) + goto out; + + if (!(data->d_spb || data->m_spb)) { + gf_log (this->name, GF_LOG_WARNING, "Cannot set " + "replica.split-brain-choice on %s. File is" + " not in data/metadata split-brain.", + uuid_utoa (loc->gfid)); + ret = -1; + op_errno = EINVAL; + goto out; + } + + LOCK(&inode->lock); + { + ret = __afr_inode_ctx_get (this, inode, &ctx); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get" + "inode_ctx for %s", loc->name); + goto unlock; + } + + ctx->spb_choice = data->spb_child_index; + + /* Possible changes in spb-choice : + * -1 to valid : ref and inject timer + * + * valid to valid : cancel timer and inject new one + * + * valid to -1 : cancel timer and unref + * + * -1 to -1 : do not do anything + */ + + /* ctx->timer is NULL iff previous value of + * ctx->spb_choice is -1 + */ + if (ctx->timer) { + if (ctx->spb_choice == -1) { + gf_timer_call_cancel (this->ctx, ctx->timer); + ctx->timer = NULL; + inode_unref (inode); + goto unlock; + } + goto reset_timer; + } else { + if (ctx->spb_choice == -1) + goto unlock; + } + + inode = inode_ref (loc->inode); + goto set_timer; + +reset_timer: + gf_timer_call_cancel (this->ctx, ctx->timer); + ctx->timer = NULL; + +set_timer: + ctx->timer = gf_timer_call_after (this->ctx, delta, + afr_set_split_brain_choice_cbk, + inode); + } +unlock: + UNLOCK(&inode->lock); + inode_invalidate (inode); +out: + if (data) + GF_FREE (data); + AFR_STACK_UNWIND (setxattr, frame, ret, op_errno, NULL); + return 0; +} int afr_accused_fill (xlator_t *this, dict_t *xdata, unsigned char *accused, @@ -3589,6 +3725,7 @@ afr_forget (xlator_t *this, inode_t *inode) uint64_t ctx_int = 0; afr_inode_ctx_t *ctx = NULL; + afr_spb_choice_timeout_cancel (this, inode); inode_ctx_del (inode, this, &ctx_int); if (!ctx_int) return 0; @@ -4552,10 +4689,10 @@ out: } int -afr_set_split_brain_status (call_frame_t *frame, xlator_t *this, - struct afr_reply *replies, - afr_transaction_type type, - gf_boolean_t *spb) +_afr_is_split_brain (call_frame_t *frame, xlator_t *this, + struct afr_reply *replies, + afr_transaction_type type, + gf_boolean_t *spb) { afr_private_t *priv = NULL; uint64_t *witness = NULL; @@ -4584,6 +4721,37 @@ afr_set_split_brain_status (call_frame_t *frame, xlator_t *this, } int +afr_is_split_brain (call_frame_t *frame, xlator_t *this, inode_t *inode, + uuid_t gfid, gf_boolean_t *d_spb, gf_boolean_t *m_spb) +{ + int ret = -1; + afr_private_t *priv = NULL; + struct afr_reply *replies = NULL; + + priv = this->private; + + replies = alloca0 (sizeof (*replies) * priv->child_count); + + ret = afr_selfheal_unlocked_discover (frame, inode, gfid, replies); + if (ret) + goto out; + + ret = _afr_is_split_brain (frame, this, replies, + AFR_DATA_TRANSACTION, d_spb); + if (ret) + goto out; + + ret = _afr_is_split_brain (frame, this, replies, + AFR_METADATA_TRANSACTION, m_spb); +out: + if (replies) { + afr_replies_wipe (replies, priv->child_count); + replies = NULL; + } + return ret; +} + +int afr_get_split_brain_status (call_frame_t *frame, xlator_t *this, loc_t *loc) { gf_boolean_t d_spb = _gf_false; @@ -4594,7 +4762,6 @@ afr_get_split_brain_status (call_frame_t *frame, xlator_t *this, loc_t *loc) char *choices = NULL; char *status = NULL; dict_t *dict = NULL; - struct afr_reply *replies = NULL; inode_t *inode = NULL; afr_private_t *priv = NULL; xlator_t **children = NULL; @@ -4605,7 +4772,6 @@ afr_get_split_brain_status (call_frame_t *frame, xlator_t *this, loc_t *loc) inode = afr_inode_find (this, loc->gfid); if (!inode) goto out; - replies = alloca0 (sizeof (*replies) * priv->child_count); /* Calculation for string length : * (child_count X length of child-name) + strlen (" Choices :") @@ -4615,23 +4781,9 @@ afr_get_split_brain_status (call_frame_t *frame, xlator_t *this, loc_t *loc) */ choices = alloca0 (priv->child_count * (256 + strlen ("-client-00,")) + strlen (" Choices:")); - ret = afr_selfheal_unlocked_discover (frame, inode, loc->gfid, replies); - if (ret) { - op_errno = -ret; - ret = -1; - goto out; - } - - ret = afr_set_split_brain_status (frame, this, replies, - AFR_DATA_TRANSACTION, &d_spb); - if (ret) { - op_errno = -ret; - ret = -1; - goto out; - } - ret = afr_set_split_brain_status (frame, this, replies, - AFR_METADATA_TRANSACTION, &m_spb); + ret = afr_is_split_brain (frame, this, inode, loc->gfid, &d_spb, + &m_spb); if (ret) { op_errno = -ret; ret = -1; @@ -4678,8 +4830,6 @@ out: AFR_STACK_UNWIND (getxattr, frame, ret, op_errno, dict, NULL); if (dict) dict_unref (dict); - if (replies) - afr_replies_wipe (replies, priv->child_count); if (inode) inode_unref (inode); return ret; |