diff options
author | karthik-us <ksubrahm@redhat.com> | 2018-06-05 15:57:16 +0530 |
---|---|---|
committer | karthik-us <ksubrahm@redhat.com> | 2018-07-16 22:01:34 +0530 |
commit | 762dff25c46e3be3b0e72bbdb63670edd5e96f17 (patch) | |
tree | 008d0046d43d477a1778a5a18839ef8dddb01d75 /xlators/cluster/afr/src | |
parent | 7dd08a4dd056f8b721d56012769cf299cd1afb53 (diff) |
cluster/afr: Mark dirty for entry transactions for quorum failures
Problem:
If an entry creation transaction fails on quprum number of bricks
it might end up setting the pending changelogs on the file itself
on the brick where it got created. But the parent does not have
any entry pending marker set. This will lead to the entry not
getting healed by the self heal daemon automatically.
Fix:
For entry transactions mark dirty on the parent if it fails on
quorum number of bricks, so that the heal can do conservative
merge and entry gets healed by shd.
Change-Id: I56448932dd409b3ddb095e2ae32e037b6157a607
fixes: bz#1586020
Signed-off-by: karthik-us <ksubrahm@redhat.com>
Diffstat (limited to 'xlators/cluster/afr/src')
-rw-r--r-- | xlators/cluster/afr/src/afr-transaction.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/xlators/cluster/afr/src/afr-transaction.c b/xlators/cluster/afr/src/afr-transaction.c index 61abf4aa090..34f238f1cc8 100644 --- a/xlators/cluster/afr/src/afr-transaction.c +++ b/xlators/cluster/afr/src/afr-transaction.c @@ -782,8 +782,38 @@ afr_has_fop_cbk_quorum (call_frame_t *frame) return afr_has_quorum (success, this); } +gf_boolean_t +afr_need_dirty_marking (call_frame_t *frame, xlator_t *this) +{ + afr_private_t *priv = this->private; + afr_local_t *local = NULL; + gf_boolean_t need_dirty = _gf_false; + + local = frame->local; + + if (!priv->quorum_count || !local->optimistic_change_log) + return _gf_false; + + if (local->transaction.type == AFR_DATA_TRANSACTION || + local->transaction.type == AFR_METADATA_TRANSACTION) + return _gf_false; + + if (AFR_COUNT (local->transaction.failed_subvols, priv->child_count) == + priv->child_count) + return _gf_false; + + if (priv->arbiter_count) { + if (!afr_has_arbiter_fop_cbk_quorum (frame)) + need_dirty = _gf_true; + } else if (!afr_has_fop_cbk_quorum (frame)) { + need_dirty = _gf_true; + } + + return need_dirty; +} + void -afr_handle_quorum (call_frame_t *frame) +afr_handle_quorum (call_frame_t *frame, xlator_t *this) { afr_local_t *local = NULL; afr_private_t *priv = NULL; @@ -834,11 +864,15 @@ afr_handle_quorum (call_frame_t *frame) return; } + if (afr_need_dirty_marking (frame, this)) + goto set_response; + for (i = 0; i < priv->child_count; i++) { if (local->transaction.pre_op[i]) afr_transaction_fop_failed (frame, frame->this, i); } +set_response: local->op_ret = -1; local->op_errno = afr_final_errno (local, priv); if (local->op_errno == 0) @@ -973,9 +1007,17 @@ afr_changelog_post_op_now (call_frame_t *frame, xlator_t *this) int nothing_failed = 1; gf_boolean_t need_undirty = _gf_false; - afr_handle_quorum (frame); + afr_handle_quorum (frame, this); local = frame->local; - idx = afr_index_for_transaction_type (local->transaction.type); + idx = afr_index_for_transaction_type (local->transaction.type); + + xattr = dict_new (); + if (!xattr) { + local->op_ret = -1; + local->op_errno = ENOMEM; + afr_changelog_post_op_done (frame, this); + goto out; + } nothing_failed = afr_txn_nothing_failed (frame, this); @@ -985,6 +1027,11 @@ afr_changelog_post_op_now (call_frame_t *frame, xlator_t *this) need_undirty = _gf_true; if (local->op_ret < 0 && !nothing_failed) { + if (afr_need_dirty_marking (frame, this)) { + local->dirty[idx] = hton32(1); + goto set_dirty; + } + afr_changelog_post_op_done (frame, this); goto out; } @@ -1001,14 +1048,6 @@ afr_changelog_post_op_now (call_frame_t *frame, xlator_t *this) goto out; } - xattr = dict_new (); - if (!xattr) { - local->op_ret = -1; - local->op_errno = ENOMEM; - afr_changelog_post_op_done (frame, this); - goto out; - } - for (i = 0; i < priv->child_count; i++) { if (local->transaction.failed_subvols[i]) local->pending[i][idx] = hton32(1); @@ -1035,6 +1074,7 @@ afr_changelog_post_op_now (call_frame_t *frame, xlator_t *this) else local->dirty[idx] = hton32(0); +set_dirty: ret = dict_set_static_bin (xattr, AFR_DIRTY, local->dirty, sizeof(int) * AFR_NUM_CHANGE_LOGS); if (ret) { |