diff options
author | Ravishankar N <ravishankar@redhat.com> | 2013-07-24 19:11:49 +0000 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2013-08-07 03:35:10 -0700 |
commit | 0f77e30c903e6f71f30dfd6165914a43998a164f (patch) | |
tree | a67f0cfbea5b694132da08c9f656ed4ce65719be /xlators/cluster | |
parent | 1feaebfe0ae140ecafd5c37a0ce1bb5f0a1ac0cf (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>
Diffstat (limited to 'xlators/cluster')
-rw-r--r-- | xlators/cluster/afr/src/afr-common.c | 5 |
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; + } } |