summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/afr/src/afr-transaction.c
diff options
context:
space:
mode:
authorkarthik-us <ksubrahm@redhat.com>2018-06-05 15:57:16 +0530
committerkarthik-us <ksubrahm@redhat.com>2018-07-16 22:01:34 +0530
commit762dff25c46e3be3b0e72bbdb63670edd5e96f17 (patch)
tree008d0046d43d477a1778a5a18839ef8dddb01d75 /xlators/cluster/afr/src/afr-transaction.c
parent7dd08a4dd056f8b721d56012769cf299cd1afb53 (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/afr-transaction.c')
-rw-r--r--xlators/cluster/afr/src/afr-transaction.c62
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) {