diff options
-rw-r--r-- | tests/bugs/replicate/bug-1586020-mark-dirty-for-entry-txn-on-quorum-failure.t | 73 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-transaction.c | 62 |
2 files changed, 124 insertions, 11 deletions
diff --git a/tests/bugs/replicate/bug-1586020-mark-dirty-for-entry-txn-on-quorum-failure.t b/tests/bugs/replicate/bug-1586020-mark-dirty-for-entry-txn-on-quorum-failure.t new file mode 100644 index 00000000000..7fec3b442d6 --- /dev/null +++ b/tests/bugs/replicate/bug-1586020-mark-dirty-for-entry-txn-on-quorum-failure.t @@ -0,0 +1,73 @@ +#!/bin/bash + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc + +cleanup; + +function create_files { + local i=1 + while (true) + do + dd if=/dev/zero of=$M0/file$i bs=1M count=10 + if [ -e $B0/${V0}0/file$i ] && [ -e $B0/${V0}1/file$i ]; then + ((i++)) + else + break + fi + done + echo $i +} + +TEST glusterd + +#Create brick partitions +TEST truncate -s 100M $B0/brick0 +TEST truncate -s 100M $B0/brick1 +#Have the 3rd brick of a higher size to test the scenario of entry transaction +#passing on only one brick and not on other bricks. +TEST truncate -s 110M $B0/brick2 +LO1=`SETUP_LOOP $B0/brick0` +TEST [ $? -eq 0 ] +TEST MKFS_LOOP $LO1 +LO2=`SETUP_LOOP $B0/brick1` +TEST [ $? -eq 0 ] +TEST MKFS_LOOP $LO2 +LO3=`SETUP_LOOP $B0/brick2` +TEST [ $? -eq 0 ] +TEST MKFS_LOOP $LO3 +TEST mkdir -p $B0/${V0}0 $B0/${V0}1 $B0/${V0}2 +TEST MOUNT_LOOP $LO1 $B0/${V0}0 +TEST MOUNT_LOOP $LO2 $B0/${V0}1 +TEST MOUNT_LOOP $LO3 $B0/${V0}2 + +TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} +TEST $CLI volume start $V0 +TEST $CLI volume set $V0 performance.write-behind off +TEST $CLI volume set $V0 self-heal-daemon off +TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0 + +i=$(create_files) +TEST ! ls $B0/${V0}0/file$i +TEST ! ls $B0/${V0}1/file$i +TEST ls $B0/${V0}2/file$i +EXPECT "000000000000000000000001" get_hex_xattr trusted.afr.dirty $B0/${V0}2 +EXPECT "000000010000000100000000" get_hex_xattr trusted.afr.$V0-client-0 $B0/${V0}2/file$i +EXPECT "000000010000000100000000" get_hex_xattr trusted.afr.$V0-client-1 $B0/${V0}2/file$i + +TEST $CLI volume set $V0 self-heal-daemon on +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 2 +TEST rm -f $M0/file1 + +TEST $CLI volume heal $V0 +EXPECT_WITHIN $HEAL_TIMEOUT "0" get_pending_heal_count $V0 +TEST force_umount $M0 +TEST $CLI volume stop $V0 +EXPECT 'Stopped' volinfo_field $V0 'Status'; +TEST $CLI volume delete $V0; +UMOUNT_LOOP ${B0}/${V0}{0,1,2} +rm -f ${B0}/brick{0,1,2} +cleanup; 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) { |