summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRavishankar N <ravishankar@redhat.com>2013-07-24 19:11:49 +0000
committerAnand Avati <avati@redhat.com>2013-08-07 03:35:10 -0700
commit0f77e30c903e6f71f30dfd6165914a43998a164f (patch)
treea67f0cfbea5b694132da08c9f656ed4ce65719be
parent1feaebfe0ae140ecafd5c37a0ce1bb5f0a1ac0cf (diff)
afr: check for non-zero call_count before doing a stack wind
When one of the bricks of a 1x2 replicate volume is down, writes to the volume is causing a race between afr_flush_wrapper() and afr_flush_cbk(). The latter frees up the call_frame's local variables in the unwind, while the former accesses them in the for loop and sending a stack wind the second time. This causes the FUSE mount process (glusterfs) toa receive a SIGSEGV when the corresponding unwind is hit. This patch adds the call_count check which was removed when afr_flush_wrapper() was introduced in commit 29619b4e Change-Id: I87d12ef39ea61cc4c8244c7f895b7492b90a7042 BUG: 988182 Signed-off-by: Ravishankar N <ravishankar@redhat.com> Reviewed-on: http://review.gluster.org/5393 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com> Reviewed-by: Anand Avati <avati@redhat.com>
-rw-r--r--xlators/cluster/afr/src/afr-common.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/xlators/cluster/afr/src/afr-common.c b/xlators/cluster/afr/src/afr-common.c
index 79644b74086..030256417f0 100644
--- a/xlators/cluster/afr/src/afr-common.c
+++ b/xlators/cluster/afr/src/afr-common.c
@@ -2592,9 +2592,11 @@ afr_flush_wrapper (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata)
int i = 0;
afr_local_t *local = NULL;
afr_private_t *priv = NULL;
+ int call_count = -1;
priv = this->private;
local = frame->local;
+ call_count = local->call_count;
for (i = 0; i < priv->child_count; i++) {
if (local->child_up[i]) {
@@ -2603,6 +2605,9 @@ afr_flush_wrapper (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata)
priv->children[i],
priv->children[i]->fops->flush,
local->fd, NULL);
+ if (!--call_count)
+ break;
+
}
}