diff options
-rw-r--r-- | tests/bugs/bug-1139230.t | 58 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heal-common.c | 25 | ||||
-rw-r--r-- | xlators/cluster/afr/src/afr-transaction.c | 46 |
3 files changed, 88 insertions, 41 deletions
diff --git a/tests/bugs/bug-1139230.t b/tests/bugs/bug-1139230.t new file mode 100644 index 00000000000..24317dd5f27 --- /dev/null +++ b/tests/bugs/bug-1139230.t @@ -0,0 +1,58 @@ +#!/bin/bash +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../afr.rc + +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume info; + +# Create a 1X2 replica +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}-{0,1} +EXPECT 'Created' volinfo_field $V0 'Status'; + +# Volume start +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +# FUSE Mount +TEST glusterfs -s $H0 --volfile-id $V0 $M0 + +TEST mkdir -p $M0/one + +# Kill a brick +TEST kill_brick $V0 $H0 $B0/${V0}-1 + +TEST `echo "A long" > $M0/one/two` + +# Start force +TEST $CLI volume start $V0 force + +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +EXPECT_WITHIN $HEAL_TIMEOUT "Y" is_dir_heal_done $B0/${V0}-0 $B0/${V0}-1 one +EXPECT_WITHIN $HEAL_TIMEOUT "Y" is_file_heal_done $B0/${V0}-0 $B0/${V0}-1 one/two + +# Pending xattrs should be set for all the bricks once self-heal is done +# Check pending xattrs +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-0/one trusted.afr.$V0-client-0 +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-0/one trusted.afr.$V0-client-1 +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-1/one trusted.afr.$V0-client-0 +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-1/one trusted.afr.$V0-client-1 +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-0/one trusted.afr.dirty +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-1/one trusted.afr.dirty + +TEST `echo "time ago" > $M0/one/three` + +# Pending xattrs should be set for all the bricks once transaction is done +# Check pending xattrs +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-0/one/three trusted.afr.$V0-client-0 +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-0/one/three trusted.afr.$V0-client-1 +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-1/one/three trusted.afr.$V0-client-0 +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-1/one/three trusted.afr.$V0-client-1 +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-0/one/three trusted.afr.dirty +EXPECT "0x000000000000000000000000" afr_get_changelog_xattr $B0/${V0}-1/one/three trusted.afr.dirty + +cleanup; diff --git a/xlators/cluster/afr/src/afr-self-heal-common.c b/xlators/cluster/afr/src/afr-self-heal-common.c index ab1552a0224..0158948d728 100644 --- a/xlators/cluster/afr/src/afr-self-heal-common.c +++ b/xlators/cluster/afr/src/afr-self-heal-common.c @@ -75,24 +75,19 @@ afr_selfheal_output_xattr (xlator_t *this, afr_transaction_type type, if (!xattr) return NULL; - if (output_dirty[subvol]) { - /* clear dirty */ - raw = GF_CALLOC (sizeof(int), AFR_NUM_CHANGE_LOGS, gf_afr_mt_int32_t); - if (!raw) - goto err; - - raw[idx] = hton32 (output_dirty[subvol]); - ret = dict_set_bin (xattr, AFR_DIRTY, raw, - sizeof(int) * AFR_NUM_CHANGE_LOGS); - if (ret) - goto err; - } + /* clear dirty */ + raw = GF_CALLOC (sizeof(int), AFR_NUM_CHANGE_LOGS, gf_afr_mt_int32_t); + if (!raw) + goto err; + + raw[idx] = hton32 (output_dirty[subvol]); + ret = dict_set_bin (xattr, AFR_DIRTY, raw, + sizeof(int) * AFR_NUM_CHANGE_LOGS); + if (ret) + goto err; /* clear/set pending */ for (j = 0; j < priv->child_count; j++) { - if (!output_matrix[subvol][j]) - continue; - raw = GF_CALLOC (sizeof(int), AFR_NUM_CHANGE_LOGS, gf_afr_mt_int32_t); if (!raw) diff --git a/xlators/cluster/afr/src/afr-transaction.c b/xlators/cluster/afr/src/afr-transaction.c index a2eab3494e3..d287e6ab66c 100644 --- a/xlators/cluster/afr/src/afr-transaction.c +++ b/xlators/cluster/afr/src/afr-transaction.c @@ -239,12 +239,8 @@ afr_set_pending_dict (afr_private_t *priv, dict_t *xattr, int **pending) { int i = 0; int ret = 0; - int pending_zero[AFR_NUM_CHANGE_LOGS] = {0, }; for (i = 0; i < priv->child_count; i++) { - if (!memcmp (pending_zero, pending[i], sizeof (pending_zero))) - /* don't set xattrs for non-pending servers */ - continue; ret = dict_set_static_bin (xattr, priv->pending_key[i], pending[i], @@ -605,33 +601,31 @@ afr_changelog_post_op_now (call_frame_t *frame, xlator_t *this) goto out; } - if (need_undirty) { + if (need_undirty) local->dirty[idx] = hton32(-1); + else + local->dirty[idx] = hton32(0); - ret = dict_set_static_bin (xattr, AFR_DIRTY, local->dirty, - sizeof(int) * AFR_NUM_CHANGE_LOGS); - if (ret) { - local->op_ret = -1; - local->op_errno = ENOMEM; - afr_changelog_post_op_done (frame, this); - goto out; - } - + ret = dict_set_static_bin (xattr, AFR_DIRTY, local->dirty, + sizeof(int) * AFR_NUM_CHANGE_LOGS); + if (ret) { + local->op_ret = -1; + local->op_errno = ENOMEM; + afr_changelog_post_op_done (frame, this); + goto out; } - if (!nothing_failed) { - for (i = 0; i < priv->child_count; i++) { - if (local->transaction.failed_subvols[i]) - local->pending[i][idx] = hton32(1); - } - ret = afr_set_pending_dict (priv, xattr, local->pending); - if (ret < 0) { - 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); + } + ret = afr_set_pending_dict (priv, xattr, local->pending); + if (ret < 0) { + local->op_ret = -1; + local->op_errno = ENOMEM; + afr_changelog_post_op_done (frame, this); + goto out; } afr_changelog_do (frame, this, xattr, afr_changelog_post_op_done); |